From a40459644b2cd6d975eaf47b36c14c1dfd502aab Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:16 +0200 Subject: [PATCH 01/11] #1263 - creating new module for view-helper --- pom.xml | 3 +- view-helper/pom.xml | 70 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 view-helper/pom.xml diff --git a/pom.xml b/pom.xml index 46429c75af7c..4285dafabfb0 100644 --- a/pom.xml +++ b/pom.xml @@ -242,7 +242,8 @@ version-number virtual-proxy visitor - backpressure + backpressure + view-helper diff --git a/view-helper/pom.xml b/view-helper/pom.xml new file mode 100644 index 000000000000..e2f3afca3a08 --- /dev/null +++ b/view-helper/pom.xml @@ -0,0 +1,70 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + view-helper + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.value.object.App + + + + + + + + + From a225935682d8b87f673d03b66cd95812bcb54373 Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:16 +0200 Subject: [PATCH 02/11] #1263 - creating Product and ProductViewModel --- .../main/java/com/iluwatar/viewhelper/Product.java | 11 +++++++++++ .../com/iluwatar/viewhelper/ProductViewModel.java | 7 +++++++ 2 files changed, 18 insertions(+) create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/Product.java create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java b/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java new file mode 100644 index 000000000000..39eabb70f9d6 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java @@ -0,0 +1,11 @@ +package com.iluwatar.viewhelper; + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * Definition of product. + */ + +public record Product(String name, BigDecimal price, LocalDate releaseDate, boolean discounted) { +} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java new file mode 100644 index 000000000000..b18d8942fbff --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java @@ -0,0 +1,7 @@ +package com.iluwatar.viewhelper; + +/** + * Class defining formatted display data of a {@link Product}. + */ +public record ProductViewModel(String name, String price, String releasedDate) { +} From b365be5f049df1f75bcca6a941496a9f669bfa46 Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:16 +0200 Subject: [PATCH 03/11] #1263 - creating interfaces for View and ViewHelper --- view-helper/src/main/java/com/iluwatar/viewhelper/View.java | 6 ++++++ .../src/main/java/com/iluwatar/viewhelper/ViewHelper.java | 5 +++++ 2 files changed, 11 insertions(+) create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/View.java create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/View.java b/view-helper/src/main/java/com/iluwatar/viewhelper/View.java new file mode 100644 index 000000000000..88e8c317efef --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/View.java @@ -0,0 +1,6 @@ +package com.iluwatar.viewhelper; + +public interface View { + + void render(V data); +} \ No newline at end of file diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java new file mode 100644 index 000000000000..faa6d70dd228 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java @@ -0,0 +1,5 @@ +package com.iluwatar.viewhelper; + +public interface ViewHelper { + V prepare(M source); +} From 69f020bca1e3528e10b2b6c7f1b3699dd95682ca Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:16 +0200 Subject: [PATCH 04/11] #1263 - creating ProductViewHelper and its test --- .../viewhelper/ProductViewHelper.java | 23 ++++++++++++ .../viewhelper/ProductViewHelperTest.java | 36 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java create mode 100644 view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java new file mode 100644 index 000000000000..0399c8903715 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java @@ -0,0 +1,23 @@ +package com.iluwatar.viewhelper; + +import static java.time.format.DateTimeFormatter.ISO_DATE; +import static java.util.Locale.US; + +import java.text.NumberFormat; + +/** + * Formats a {@link Product} into a {@link ProductViewModel}. + */ +public class ProductViewHelper implements ViewHelper { + + private static final String DISCOUNT_TAG = " ON SALE"; + + @Override + public ProductViewModel prepare(Product product) { + var displayName = product.name() + (product.discounted() ? DISCOUNT_TAG : ""); + var priceWithCurrency = NumberFormat.getCurrencyInstance(US).format(product.price()); + var formattedDate = product.releaseDate().format(ISO_DATE); + + return new ProductViewModel(displayName, priceWithCurrency, formattedDate); + } +} diff --git a/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java b/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java new file mode 100644 index 000000000000..a1409b83f36d --- /dev/null +++ b/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java @@ -0,0 +1,36 @@ +package com.iluwatar.viewhelper; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigDecimal; +import java.time.LocalDate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ProductViewHelperTest { + + private ProductViewHelper helper; + + @BeforeEach + void setUp() { + helper = new ProductViewHelper(); + } + + @Test + void shouldFormatProductWithoutDiscount() { + var product = new Product("X", new BigDecimal("10.00"), LocalDate.of(2025, 1, 1), false); + ProductViewModel viewModel = helper.prepare(product); + + assertEquals("X", viewModel.name()); + assertEquals("$10.00", viewModel.price()); + assertEquals("2025-01-01", viewModel.releasedDate()); + } + + @Test + void shouldFormatProductWithDiscount() { + var product = new Product("X", new BigDecimal("10.00"), LocalDate.of(2025, 1, 1), true); + ProductViewModel viewModel = helper.prepare(product); + + assertEquals("X ON SALE", viewModel.name()); // locale follows JVM default + } +} \ No newline at end of file From 442e1f89599af4fd29717340de97fbeae45af2c2 Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:17 +0200 Subject: [PATCH 05/11] #1263 - creating Console View for Product --- .../iluwatar/viewhelper/ConsoleProductView.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java new file mode 100644 index 000000000000..c2ff686f4fa5 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java @@ -0,0 +1,14 @@ +package com.iluwatar.viewhelper; + +import lombok.extern.slf4j.Slf4j; + +/** + * Renders {@link ProductViewModel} to the console. + */ +@Slf4j +public class ConsoleProductView implements View { + @Override + public void render(ProductViewModel productViewModel) { + LOGGER.info(productViewModel.toString()); + } +} From bf56994bd33c7501224b32b39a9e4200c443d61b Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:17 +0200 Subject: [PATCH 06/11] #1263 - creating ProductController --- .../viewhelper/ProductController.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java new file mode 100644 index 000000000000..dc842cb14db3 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java @@ -0,0 +1,21 @@ +package com.iluwatar.viewhelper; + +/** + * Controller delegates a {@link Product} to {@link ProductViewHelper} and then to {@link ConsoleProductView}. + */ +public class ProductController { + + private final ViewHelper viewHelper; + private final View view; + + public ProductController(ViewHelper viewHelper, + View view) { + this.viewHelper = viewHelper; + this.view = view; + } + + /** Passes the product to the helper for formatting and then forwards formatted product to the view. */ + public void handle(Product product) { + view.render(viewHelper.prepare(product)); + } +} From 1e839fab62dec9e1b8b5d6b805dc421edafbec0a Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:17 +0200 Subject: [PATCH 07/11] #1263 - creating main App and its test --- .../java/com/iluwatar/viewhelper/App.java | 56 +++++++++++++++++++ .../java/com/iluwatar/viewhelper/AppTest.java | 39 +++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/App.java create mode 100644 view-helper/src/test/java/com/iluwatar/viewhelper/AppTest.java diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/App.java b/view-helper/src/main/java/com/iluwatar/viewhelper/App.java new file mode 100644 index 000000000000..4f048489656d --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/App.java @@ -0,0 +1,56 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.viewhelper; + + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** The main application class that sets up and runs the View Helper pattern demo. */ +public class App { + /** + * The entry point of the application. + * + * @param args the command line arguments + */ + public static void main(String[] args) { + // Raw Product data (no formatting, no UI tags) + var product = new Product( + "Design patterns book", + new BigDecimal("18.90"), + LocalDate.of(2025, 4, 19), + true + ); + + // Create view, viewHelper and viewHelper + var helper = new ProductViewHelper(); + var view = new ConsoleProductView(); + var controller = new ProductController(helper, view); + + // Handle “request” + controller.handle(product); + } +} diff --git a/view-helper/src/test/java/com/iluwatar/viewhelper/AppTest.java b/view-helper/src/test/java/com/iluwatar/viewhelper/AppTest.java new file mode 100644 index 000000000000..bc4a31cc43a8 --- /dev/null +++ b/view-helper/src/test/java/com/iluwatar/viewhelper/AppTest.java @@ -0,0 +1,39 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.viewhelper; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import org.junit.jupiter.api.Test; + +/** Application test */ +class AppTest { + + @Test + void shouldExecuteApplicationWithoutException() { + assertDoesNotThrow(() -> App.main(new String[] {})); + } +} From faa7d0a64062df3c5137b430b51ebb861d83971f Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:18 +0200 Subject: [PATCH 08/11] #1263 - adding license header --- .../viewhelper/ConsoleProductView.java | 24 +++++++++++++++++++ .../java/com/iluwatar/viewhelper/Product.java | 24 +++++++++++++++++++ .../viewhelper/ProductController.java | 24 +++++++++++++++++++ .../viewhelper/ProductViewHelper.java | 24 +++++++++++++++++++ .../iluwatar/viewhelper/ProductViewModel.java | 24 +++++++++++++++++++ .../java/com/iluwatar/viewhelper/View.java | 24 +++++++++++++++++++ .../com/iluwatar/viewhelper/ViewHelper.java | 24 +++++++++++++++++++ .../viewhelper/ProductViewHelperTest.java | 24 +++++++++++++++++++ 8 files changed, 192 insertions(+) diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java index c2ff686f4fa5..33c6d83b41a8 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java @@ -1,3 +1,27 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.viewhelper; import lombok.extern.slf4j.Slf4j; diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java b/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java index 39eabb70f9d6..7078ff6bfd64 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java @@ -1,3 +1,27 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.viewhelper; import java.math.BigDecimal; diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java index dc842cb14db3..645d98f57823 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java @@ -1,3 +1,27 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.viewhelper; /** diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java index 0399c8903715..88116519c7c4 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java @@ -1,3 +1,27 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.viewhelper; import static java.time.format.DateTimeFormatter.ISO_DATE; diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java index b18d8942fbff..07ac880cd937 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java @@ -1,3 +1,27 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.viewhelper; /** diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/View.java b/view-helper/src/main/java/com/iluwatar/viewhelper/View.java index 88e8c317efef..2ce9f030e746 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/View.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/View.java @@ -1,3 +1,27 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.viewhelper; public interface View { diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java index faa6d70dd228..68756f46585d 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java @@ -1,3 +1,27 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.viewhelper; public interface ViewHelper { diff --git a/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java b/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java index a1409b83f36d..66fc0461dce5 100644 --- a/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java +++ b/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java @@ -1,3 +1,27 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package com.iluwatar.viewhelper; import static org.junit.jupiter.api.Assertions.assertEquals; From 3dbc8ef4ba9628ded5f440d588f727f0e6907a65 Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:18 +0200 Subject: [PATCH 09/11] #1263 - keeping module in alphabetical order --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4285dafabfb0..f706f9845b0b 100644 --- a/pom.xml +++ b/pom.xml @@ -240,10 +240,10 @@ update-method value-object version-number + view-helper virtual-proxy visitor backpressure - view-helper From 9904085176da28706e7a822d24966878a406fd87 Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 20:26:18 +0200 Subject: [PATCH 10/11] #1263 - creating README and diagrams --- view-helper/README.md | 98 ++++++++++++++++++ .../etc/view-helper-sequence-diagram.png | Bin 0 -> 27969 bytes .../etc/view-helper-sequence-diagram.puml | 15 +++ view-helper/etc/view-helper.png | Bin 0 -> 56099 bytes view-helper/etc/view-helper.puml | 45 ++++++++ 5 files changed, 158 insertions(+) create mode 100644 view-helper/README.md create mode 100644 view-helper/etc/view-helper-sequence-diagram.png create mode 100644 view-helper/etc/view-helper-sequence-diagram.puml create mode 100644 view-helper/etc/view-helper.png create mode 100644 view-helper/etc/view-helper.puml diff --git a/view-helper/README.md b/view-helper/README.md new file mode 100644 index 000000000000..fbc93acba6fd --- /dev/null +++ b/view-helper/README.md @@ -0,0 +1,98 @@ +--- +title: "View Helper Pattern in Java: Simplifying Presentation Logic in MVC Applications" +shortTitle: View Helper +description: "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." +category: Architectural +language: en +tag: + - Architecture + - Presentation + - Decoupling + - Code reuse +--- + +## Intent of View Helper Design Pattern +The 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. + +## Detailed Explanation with Real‑World Analogy +Real‑world example +> 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. +> +> 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. + +### In plain words +> 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. + +### Sequence diagram +![Sequence diagram for View Helper](etc/view-helper-sequence-diagram.png) + +## Programmatic Example of View Helper Pattern in Java +Raw domain object +```java +public record Product(String name, BigDecimal price, LocalDate releaseDate, boolean discounted) {} +``` + +View model object for display +```java +public record ProductViewModel(String name, String price, String releasedDate) {} +``` + +View Helper formats data for display +```java +class ProductViewHelper implements ViewHelper { + + private static final String DISCOUNT_TAG = " (ON SALE)"; + + public ProductViewModel prepare(Product product) { + var displayName = product.name() + (product.discounted() ? DISCOUNT_TAG : ""); + var priceWithCurrency = NumberFormat.getCurrencyInstance(US).format(product.price()); + var formattedDate = product.releaseDate().format(ISO_DATE); + + return new ProductViewModel(displayName, priceWithCurrency, formattedDate); + } +} +``` + +View renders the formatted data +```java +public class ConsoleProductView implements View { + + @Override + public void render(ProductViewModel productViewModel) { + LOGGER.info(productViewModel.toString()); + } +} +``` +The `App.java` class simulates how the View Helper pattern works in a real application. It starts with a raw `Product` object containing unformatted data. +Then it: +1. Initializes a helper (`ProductViewHelper`) to format the product data for display. +1. Creates a view (`ConsoleProductView`) to render the formatted data. +1. Uses a controller (`ProductController`) to coordinate the flow between raw data, helper logic, and view rendering. + +Finally, 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. + +## When to Use the View Helper Pattern in Java +Use 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. + +## Real‑World Uses of View Helper Pattern in Java +The 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. + +## Benefits and Trade‑offs +Benefits: +* Separation of concerns: Keeps view templates clean by moving logic into dedicated helpers. +* Reusability: Common formatting and display logic can be reused across multiple views. +* Improved maintainability: Easier to update presentation logic without touching the view. +* Testability: Helpers can be unit tested independently from the UI layer. + +Trade‑offs: +* Added complexity: Introduces extra classes, which may feel unnecessary for very simple views. +* Overuse risk: Excessive use of helpers can spread logic thinly across many files, making it harder to trace behavior. +* Tight coupling risk: If not designed carefully, helpers can become tightly coupled to specific views or data formats. + +## Related Java Design Patterns +* [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. +* [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. +* [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. + +## References & Credits +* [Core J2EE Patterns: View Helper.](https://www.oracle.com/java/technologies/viewhelper.html) diff --git a/view-helper/etc/view-helper-sequence-diagram.png b/view-helper/etc/view-helper-sequence-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..22e53c6b8afe625ae8604ca8f37659e69e6ef8e2 GIT binary patch literal 27969 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 literal 0 HcmV?d00001 diff --git a/view-helper/etc/view-helper-sequence-diagram.puml b/view-helper/etc/view-helper-sequence-diagram.puml new file mode 100644 index 000000000000..d5be27e51510 --- /dev/null +++ b/view-helper/etc/view-helper-sequence-diagram.puml @@ -0,0 +1,15 @@ +@startuml +actor Client +participant Controller +participant ViewHelper +participant View +participant Product +participant ProductViewModel + +Client -> Controller : handle(product) +Controller -> ViewHelper : prepare(product) +ViewHelper -> Product : access data +ViewHelper -> ProductViewModel : return formatted view model +Controller -> View : render(viewModel) +View -> Console : display output +@enduml \ No newline at end of file diff --git a/view-helper/etc/view-helper.png b/view-helper/etc/view-helper.png new file mode 100644 index 0000000000000000000000000000000000000000..9550b80d7acb2496f8ededf8ad9a85237203b28b GIT binary patch literal 56099 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 { + +render(T model) + } + + interface ViewHelper { + +prepare(S source): T + } + + class Product { + -name: String + -price: BigDecimal + -releaseDate: LocalDate + -discounted: boolean + } + + class ProductViewModel { + -name: String + -price: String + -releasedDate: String + } + + class ProductViewHelper { + +prepare(Product): ProductViewModel + } + + class ConsoleProductView { + +render(ProductViewModel) + } + + class ProductController { + -helper: ViewHelper + -view: View + +handle(Product) + } +} +Product --> ProductViewHelper +ProductViewHelper ..|> ViewHelper +ConsoleProductView ..|> View +ProductViewHelper --> ProductViewModel +ProductController --> ProductViewHelper +ProductController --> ConsoleProductView + +@enduml \ No newline at end of file From 2159f24afb2baec3506d264d6bdd19cb5347a56c Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Tue, 13 May 2025 22:57:40 +0200 Subject: [PATCH 11/11] #1263 apply spotless --- .../src/main/java/com/iluwatar/viewhelper/App.java | 14 +++++--------- .../iluwatar/viewhelper/ConsoleProductView.java | 4 +--- .../main/java/com/iluwatar/viewhelper/Product.java | 8 ++------ .../com/iluwatar/viewhelper/ProductController.java | 12 ++++++++---- .../com/iluwatar/viewhelper/ProductViewHelper.java | 4 +--- .../com/iluwatar/viewhelper/ProductViewModel.java | 7 ++----- .../main/java/com/iluwatar/viewhelper/View.java | 2 +- .../iluwatar/viewhelper/ProductViewHelperTest.java | 4 ++-- 8 files changed, 22 insertions(+), 33 deletions(-) diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/App.java b/view-helper/src/main/java/com/iluwatar/viewhelper/App.java index 4f048489656d..e427bc8f5e9b 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/App.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/App.java @@ -25,7 +25,6 @@ package com.iluwatar.viewhelper; - import java.math.BigDecimal; import java.time.LocalDate; @@ -38,16 +37,13 @@ public class App { */ public static void main(String[] args) { // Raw Product data (no formatting, no UI tags) - var product = new Product( - "Design patterns book", - new BigDecimal("18.90"), - LocalDate.of(2025, 4, 19), - true - ); + var product = + new Product( + "Design patterns book", new BigDecimal("18.90"), LocalDate.of(2025, 4, 19), true); // Create view, viewHelper and viewHelper - var helper = new ProductViewHelper(); - var view = new ConsoleProductView(); + var helper = new ProductViewHelper(); + var view = new ConsoleProductView(); var controller = new ProductController(helper, view); // Handle “request” diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java index 33c6d83b41a8..7f215a7514f6 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java @@ -26,9 +26,7 @@ import lombok.extern.slf4j.Slf4j; -/** - * Renders {@link ProductViewModel} to the console. - */ +/** Renders {@link ProductViewModel} to the console. */ @Slf4j public class ConsoleProductView implements View { @Override diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java b/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java index 7078ff6bfd64..a0a75cf24188 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java @@ -27,9 +27,5 @@ import java.math.BigDecimal; import java.time.LocalDate; -/** - * Definition of product. - */ - -public record Product(String name, BigDecimal price, LocalDate releaseDate, boolean discounted) { -} +/** Definition of product. */ +public record Product(String name, BigDecimal price, LocalDate releaseDate, boolean discounted) {} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java index 645d98f57823..836f34a33167 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java @@ -25,20 +25,24 @@ package com.iluwatar.viewhelper; /** - * Controller delegates a {@link Product} to {@link ProductViewHelper} and then to {@link ConsoleProductView}. + * Controller delegates a {@link Product} to {@link ProductViewHelper} and then to {@link + * ConsoleProductView}. */ public class ProductController { private final ViewHelper viewHelper; private final View view; - public ProductController(ViewHelper viewHelper, - View view) { + public ProductController( + ViewHelper viewHelper, View view) { this.viewHelper = viewHelper; this.view = view; } - /** Passes the product to the helper for formatting and then forwards formatted product to the view. */ + /** + * Passes the product to the helper for formatting and then forwards formatted product to the + * view. + */ public void handle(Product product) { view.render(viewHelper.prepare(product)); } diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java index 88116519c7c4..4c739e9f14a8 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java @@ -29,9 +29,7 @@ import java.text.NumberFormat; -/** - * Formats a {@link Product} into a {@link ProductViewModel}. - */ +/** Formats a {@link Product} into a {@link ProductViewModel}. */ public class ProductViewHelper implements ViewHelper { private static final String DISCOUNT_TAG = " ON SALE"; diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java index 07ac880cd937..b133fc071da1 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java @@ -24,8 +24,5 @@ */ package com.iluwatar.viewhelper; -/** - * Class defining formatted display data of a {@link Product}. - */ -public record ProductViewModel(String name, String price, String releasedDate) { -} +/** Class defining formatted display data of a {@link Product}. */ +public record ProductViewModel(String name, String price, String releasedDate) {} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/View.java b/view-helper/src/main/java/com/iluwatar/viewhelper/View.java index 2ce9f030e746..7bc822166885 100644 --- a/view-helper/src/main/java/com/iluwatar/viewhelper/View.java +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/View.java @@ -27,4 +27,4 @@ public interface View { void render(V data); -} \ No newline at end of file +} diff --git a/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java b/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java index 66fc0461dce5..49cc48556f47 100644 --- a/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java +++ b/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java @@ -55,6 +55,6 @@ void shouldFormatProductWithDiscount() { var product = new Product("X", new BigDecimal("10.00"), LocalDate.of(2025, 1, 1), true); ProductViewModel viewModel = helper.prepare(product); - assertEquals("X ON SALE", viewModel.name()); // locale follows JVM default + assertEquals("X ON SALE", viewModel.name()); // locale follows JVM default } -} \ No newline at end of file +}