Refactoring and updating of Views.

This commit is contained in:
JesseBrault0709 2024-05-05 20:54:33 +02:00
parent 2e454c6f60
commit 7e2e176e6a
6 changed files with 71 additions and 78 deletions

View File

@ -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> T asType(Class<T> 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);
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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<Object> {
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<Object> 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> T asType(Class<T> 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);
}
}
}

View File

@ -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<Object> 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;
}
}

View File

@ -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<String, Object> 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);