From 7e2e176e6ad6f0d1b0f5b9981091e3d8b7c45156 Mon Sep 17 00:00:00 2001 From: JesseBrault0709 <62299747+JesseBrault0709@users.noreply.github.com> Date: Sun, 5 May 2024 20:54:33 +0200 Subject: [PATCH] Refactoring and updating of Views. --- .../main/java/groowt/view/AbstractView.java | 34 ----------- .../java/groowt/view/GStringTemplateView.java | 2 +- .../java/groowt/view/GroovyTemplateView.java | 2 +- views/src/main/java/groowt/view/View.java | 59 ++++++++++--------- .../java/groowt/view/WritableClosureView.java | 37 ++++++++++++ .../groowt/view/GStringTemplateViewTests.java | 15 +---- 6 files changed, 71 insertions(+), 78 deletions(-) delete mode 100644 views/src/main/java/groowt/view/AbstractView.java create mode 100644 views/src/main/java/groowt/view/WritableClosureView.java diff --git a/views/src/main/java/groowt/view/AbstractView.java b/views/src/main/java/groowt/view/AbstractView.java deleted file mode 100644 index d95621e..0000000 --- a/views/src/main/java/groowt/view/AbstractView.java +++ /dev/null @@ -1,34 +0,0 @@ -package groowt.view; - -import groovy.lang.Closure; -import groovy.lang.GroovyObjectSupport; -import groovy.lang.MetaProperty; -import groovy.lang.Writable; -import org.codehaus.groovy.runtime.typehandling.GroovyCastException; - -import java.util.Map; -import java.util.stream.Collectors; - -/** - * TODO: create a Map implementation that can access the View for keys/values, or do a metaclass thing - * TODO: get rid of this and just move the asType stuff to GStringTemplateView - */ -public abstract class AbstractView extends GroovyObjectSupport implements View { - - @SuppressWarnings("unchecked") - public T asType(Class clazz) { - if (clazz.isAssignableFrom(this.getClass())) { - return (T) this; - } else if (clazz.equals(Writable.class)) { - return (T) this.asWritable(); - } else if (clazz.equals(Closure.class)) { - return (T) this.asClosure(); - } else if (clazz.equals(Map.class)) { - return (T) this.getMetaClass().getProperties().stream() - .collect(Collectors.toMap(MetaProperty::getName, metaProperty -> metaProperty.getProperty(this))); - } else { - throw new GroovyCastException(this, clazz); - } - } - -} diff --git a/views/src/main/java/groowt/view/GStringTemplateView.java b/views/src/main/java/groowt/view/GStringTemplateView.java index 0b39bd5..f9bb11b 100644 --- a/views/src/main/java/groowt/view/GStringTemplateView.java +++ b/views/src/main/java/groowt/view/GStringTemplateView.java @@ -17,7 +17,7 @@ import java.util.Map; /** * Delegates to self. */ -public class GStringTemplateView extends AbstractView { +public class GStringTemplateView implements View { private final GStringTemplateEngine engine; private final Object src; diff --git a/views/src/main/java/groowt/view/GroovyTemplateView.java b/views/src/main/java/groowt/view/GroovyTemplateView.java index a4ae0b2..8f322e4 100644 --- a/views/src/main/java/groowt/view/GroovyTemplateView.java +++ b/views/src/main/java/groowt/view/GroovyTemplateView.java @@ -7,7 +7,7 @@ import java.io.IOException; import java.io.Writer; import java.util.Map; -public class GroovyTemplateView extends AbstractView { +public class GroovyTemplateView implements View { private final Template template; diff --git a/views/src/main/java/groowt/view/View.java b/views/src/main/java/groowt/view/View.java index c3162d2..8b118af 100644 --- a/views/src/main/java/groowt/view/View.java +++ b/views/src/main/java/groowt/view/View.java @@ -2,6 +2,7 @@ package groowt.view; import groovy.lang.Closure; import groovy.lang.Writable; +import org.codehaus.groovy.runtime.DefaultGroovyMethods; import java.io.IOException; import java.io.StringWriter; @@ -10,28 +11,6 @@ import java.io.Writer; @FunctionalInterface public interface View { - /** - * TODO: consider making this a (package private?) separate class, perhaps with support for GStringTemplateViews, etc.? - */ - final class ClosureView extends Closure { - - private final View view; - - public ClosureView(View view) { - super(view, view); - this.view = view; - } - - public void doCall(Writer writer) throws IOException { - this.view.renderTo(writer); - } - - public String doCall() { - return this.view.render(); - } - - } - void renderTo(Writer writer) throws IOException; default String render() { @@ -44,15 +23,37 @@ public interface View { } } - default Writable asWritable() { - return writer -> { - this.renderTo(writer); - return writer; - }; + @SuppressWarnings("rawtypes") + default Closure asWritable() { + if (this instanceof Closure) { + return (Closure) this; + } else { + return new WritableClosureView(this); + } } - default Closure asClosure() { - return new ClosureView(this); + @SuppressWarnings("rawtypes") + default Closure asClosure() { + if (this instanceof Closure) { + return (Closure) this; + } else { + return new WritableClosureView(this); + } + } + + @SuppressWarnings("unchecked") + default T asType(Class clazz) { + if (clazz.isInstance(this)) { + return clazz.cast(this); + } else if (clazz.equals(Writable.class)) { + return (T) this.asWritable(); + } else if (clazz.equals(Closure.class)) { + return (T) this.asClosure(); + } else if (clazz.equals(String.class)) { + return (T) this.render(); + } else { + return DefaultGroovyMethods.asType(this, clazz); + } } } diff --git a/views/src/main/java/groowt/view/WritableClosureView.java b/views/src/main/java/groowt/view/WritableClosureView.java new file mode 100644 index 0000000..e9230da --- /dev/null +++ b/views/src/main/java/groowt/view/WritableClosureView.java @@ -0,0 +1,37 @@ +package groowt.view; + +import groovy.lang.Closure; +import groovy.lang.Writable; + +import java.io.IOException; +import java.io.Writer; + +final class WritableClosureView extends Closure implements View, Writable { + + private final View view; + + public WritableClosureView(View view) { + super(view, view); + this.view = view; + } + + @Override + public void renderTo(Writer writer) throws IOException { + this.view.renderTo(writer); + } + + public void doCall(Writer writer) throws IOException { + this.view.renderTo(writer); + } + + public String doCall() { + return this.view.render(); + } + + @Override + public Writer writeTo(Writer out) throws IOException { + this.view.renderTo(out); + return out; + } + +} diff --git a/views/src/test/groovy/groowt/view/GStringTemplateViewTests.java b/views/src/test/groovy/groowt/view/GStringTemplateViewTests.java index dfab154..174dbbb 100644 --- a/views/src/test/groovy/groowt/view/GStringTemplateViewTests.java +++ b/views/src/test/groovy/groowt/view/GStringTemplateViewTests.java @@ -14,8 +14,6 @@ public class GStringTemplateViewTests { private static final class GreetingView extends GStringTemplateView { - private final String greeting = "Hello, world!"; - public GreetingView(GStringTemplateEngine engine) { super(Map.of( "engine", engine, @@ -24,7 +22,7 @@ public class GStringTemplateViewTests { } public String getGreeting() { - return this.greeting; + return "Hello, world!"; } } @@ -58,19 +56,10 @@ public class GStringTemplateViewTests { final var view = new GreetingView(this.engine); final var writable = view.asWritable(); final var w = new StringWriter(); - writable.writeTo(w); + writable.call(w); assertEquals("Hello, world!", w.toString()); } - @SuppressWarnings("unchecked") - @Test - public void coerceToMap() { - final var view = new GreetingView(this.engine); - final Map map = view.asType(Map.class); - assertTrue(map.containsKey("greeting")); - assertEquals("Hello, world!", map.get("greeting")); - } - @Test public void yieldingViewSimple() { final var greetingView = new GreetingView(this.engine);