From 0213d79b0fd45dd4c294c5008db365bad70b0190 Mon Sep 17 00:00:00 2001 From: mperor Date: Sat, 18 Jan 2025 12:56:48 +0100 Subject: [PATCH 1/2] Add complex composite example --- .../structural/composite/AddressablePath.java | 34 ++++++++++++++++ .../pattern/structural/composite/File.java | 8 ++++ .../pattern/structural/composite/Folder.java | 39 +++++++++++++++++++ .../structural/composite/Nameable.java | 5 +++ .../composite/FolderCompositeTest.java | 22 +++++++++++ 5 files changed, 108 insertions(+) create mode 100644 DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/AddressablePath.java create mode 100644 DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/File.java create mode 100644 DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Folder.java create mode 100644 DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Nameable.java create mode 100644 DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/structural/composite/FolderCompositeTest.java diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/AddressablePath.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/AddressablePath.java new file mode 100644 index 0000000..558479b --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/AddressablePath.java @@ -0,0 +1,34 @@ +package pl.mperor.lab.java.design.pattern.structural.composite; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public abstract class AddressablePath implements Nameable { + + private final String name; + private Nameable parent; + + protected AddressablePath(String name) { + this.name = name; + } + + protected void setParent(Nameable parent) { + this.parent = parent; + } + + @Override + public String getName() { + return name; + } + + @Override + public String toString() { + if (parent == null) { + return name; + } + + return Stream.of(parent.toString(), name) + .collect(Collectors.joining("/")); + } + +} diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/File.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/File.java new file mode 100644 index 0000000..62656d4 --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/File.java @@ -0,0 +1,8 @@ +package pl.mperor.lab.java.design.pattern.structural.composite; + +public class File extends AddressablePath { + + protected File(String name) { + super(name); + } +} diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Folder.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Folder.java new file mode 100644 index 0000000..760c150 --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Folder.java @@ -0,0 +1,39 @@ +package pl.mperor.lab.java.design.pattern.structural.composite; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.Predicate; + +public final class Folder extends AddressablePath { + + private final AddressablePath[] paths; + + public Folder(String name, AddressablePath... paths) { + super(name); + this.paths = paths; + for (AddressablePath path : paths) { + path.setParent(this); + } + } + + public List find(Predicate nameMatcher) { + List result = new ArrayList<>(); + + Arrays.stream(paths) + .filter(path -> nameMatcher.test(path.getName())) + .map(Object::toString) + .forEach(result::add); + + Arrays.stream(paths) + .filter(Folder.class::isInstance) + .map(Folder.class::cast) + .map(complexTag -> complexTag.find(nameMatcher)) + .flatMap(Collection::stream) + .forEach(result::add); + + return result; + } + +} diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Nameable.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Nameable.java new file mode 100644 index 0000000..7330934 --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Nameable.java @@ -0,0 +1,5 @@ +package pl.mperor.lab.java.design.pattern.structural.composite; + +public interface Nameable { + String getName(); +} diff --git a/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/structural/composite/FolderCompositeTest.java b/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/structural/composite/FolderCompositeTest.java new file mode 100644 index 0000000..ff6a53a --- /dev/null +++ b/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/structural/composite/FolderCompositeTest.java @@ -0,0 +1,22 @@ +package pl.mperor.lab.java.design.pattern.structural.composite; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +class FolderCompositeTest { + + @Test + public void shouldAllowToSearchNames() { + var root = new Folder("root", + new Folder("css", new File("main.css"), new File("user.css")), + new Folder("js", new File("main.js"), new File("user.js")), + new Folder("fonts", new File("monospace.ttf")), + new Folder("images", new File("logo.png")), + new File("index.html") + ); + List paths = root.find(name -> name.contains("css")); + System.out.println(paths); + } + +} \ No newline at end of file From 5446dd5add566f985231a73e30b2a2493e9a6012 Mon Sep 17 00:00:00 2001 From: mperor Date: Thu, 22 Oct 2026 22:35:04 +0200 Subject: [PATCH 2/2] Assert folder composite search results instead of printing them --- .../design/pattern/structural/composite/Folder.java | 2 +- .../structural/composite/FolderCompositeTest.java | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Folder.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Folder.java index 760c150..4d6411d 100644 --- a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Folder.java +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/structural/composite/Folder.java @@ -29,7 +29,7 @@ public List find(Predicate nameMatcher) { Arrays.stream(paths) .filter(Folder.class::isInstance) .map(Folder.class::cast) - .map(complexTag -> complexTag.find(nameMatcher)) + .map(folder -> folder.find(nameMatcher)) .flatMap(Collection::stream) .forEach(result::add); diff --git a/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/structural/composite/FolderCompositeTest.java b/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/structural/composite/FolderCompositeTest.java index ff6a53a..499fc02 100644 --- a/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/structural/composite/FolderCompositeTest.java +++ b/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/structural/composite/FolderCompositeTest.java @@ -1,5 +1,6 @@ package pl.mperor.lab.java.design.pattern.structural.composite; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.util.List; @@ -15,8 +16,12 @@ public void shouldAllowToSearchNames() { new Folder("images", new File("logo.png")), new File("index.html") ); - List paths = root.find(name -> name.contains("css")); - System.out.println(paths); + + Assertions.assertEquals(List.of("root/css", "root/css/main.css", "root/css/user.css"), + root.find(name -> name.contains("css"))); + Assertions.assertEquals(List.of("root/js/main.js", "root/js/user.js"), + root.find(name -> name.endsWith(".js"))); + Assertions.assertEquals(List.of(), root.find(name -> name.endsWith(".exe"))); } -} \ No newline at end of file +}