Refactoring and updating of Views.
This commit is contained in:
parent
2e454c6f60
commit
7e2e176e6a
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -17,7 +17,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* Delegates to self.
|
* Delegates to self.
|
||||||
*/
|
*/
|
||||||
public class GStringTemplateView extends AbstractView {
|
public class GStringTemplateView implements View {
|
||||||
|
|
||||||
private final GStringTemplateEngine engine;
|
private final GStringTemplateEngine engine;
|
||||||
private final Object src;
|
private final Object src;
|
||||||
|
@ -7,7 +7,7 @@ import java.io.IOException;
|
|||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class GroovyTemplateView extends AbstractView {
|
public class GroovyTemplateView implements View {
|
||||||
|
|
||||||
private final Template template;
|
private final Template template;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package groowt.view;
|
|||||||
|
|
||||||
import groovy.lang.Closure;
|
import groovy.lang.Closure;
|
||||||
import groovy.lang.Writable;
|
import groovy.lang.Writable;
|
||||||
|
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
@ -10,28 +11,6 @@ import java.io.Writer;
|
|||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface View {
|
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;
|
void renderTo(Writer writer) throws IOException;
|
||||||
|
|
||||||
default String render() {
|
default String render() {
|
||||||
@ -44,15 +23,37 @@ public interface View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default Writable asWritable() {
|
@SuppressWarnings("rawtypes")
|
||||||
return writer -> {
|
default Closure asWritable() {
|
||||||
this.renderTo(writer);
|
if (this instanceof Closure) {
|
||||||
return writer;
|
return (Closure) this;
|
||||||
};
|
} else {
|
||||||
|
return new WritableClosureView(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default Closure<Object> asClosure() {
|
@SuppressWarnings("rawtypes")
|
||||||
return new ClosureView(this);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
37
views/src/main/java/groowt/view/WritableClosureView.java
Normal file
37
views/src/main/java/groowt/view/WritableClosureView.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -14,8 +14,6 @@ public class GStringTemplateViewTests {
|
|||||||
|
|
||||||
private static final class GreetingView extends GStringTemplateView {
|
private static final class GreetingView extends GStringTemplateView {
|
||||||
|
|
||||||
private final String greeting = "Hello, world!";
|
|
||||||
|
|
||||||
public GreetingView(GStringTemplateEngine engine) {
|
public GreetingView(GStringTemplateEngine engine) {
|
||||||
super(Map.of(
|
super(Map.of(
|
||||||
"engine", engine,
|
"engine", engine,
|
||||||
@ -24,7 +22,7 @@ public class GStringTemplateViewTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getGreeting() {
|
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 view = new GreetingView(this.engine);
|
||||||
final var writable = view.asWritable();
|
final var writable = view.asWritable();
|
||||||
final var w = new StringWriter();
|
final var w = new StringWriter();
|
||||||
writable.writeTo(w);
|
writable.call(w);
|
||||||
assertEquals("Hello, world!", w.toString());
|
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
|
@Test
|
||||||
public void yieldingViewSimple() {
|
public void yieldingViewSimple() {
|
||||||
final var greetingView = new GreetingView(this.engine);
|
final var greetingView = new GreetingView(this.engine);
|
||||||
|
Loading…
Reference in New Issue
Block a user