Added some convenience methods to ComponentScope and related factories, etc. Fixed RunTemplate.
This commit is contained in:
parent
e4e972ea7b
commit
e22fc1622e
@ -49,8 +49,6 @@ public abstract class AbstractViewComponent implements ViewComponent {
|
|||||||
this.template = instantiateTemplate(templateClass);
|
this.template = instantiateTemplate(templateClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setContext(ComponentContext context) {
|
public void setContext(ComponentContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package groowt.view.component.context;
|
package groowt.view.component.context;
|
||||||
|
|
||||||
|
import groovy.lang.Closure;
|
||||||
|
import groovy.lang.DelegatesTo;
|
||||||
|
import groovy.transform.stc.ClosureParams;
|
||||||
|
import groovy.transform.stc.FirstParam;
|
||||||
|
import groovy.transform.stc.SimpleType;
|
||||||
import groowt.view.component.ViewComponent;
|
import groowt.view.component.ViewComponent;
|
||||||
import groowt.view.component.runtime.RenderContext;
|
import groowt.view.component.runtime.RenderContext;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -25,6 +30,27 @@ public interface ComponentContext {
|
|||||||
return scopeClass.cast(this.getRootScope());
|
return scopeClass.cast(this.getRootScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void configureRootScope(
|
||||||
|
@ClosureParams(value = SimpleType.class, options = "groowt.view.component.context.ComponentScope")
|
||||||
|
@DelegatesTo(ComponentScope.class)
|
||||||
|
Closure<?> configure
|
||||||
|
) {
|
||||||
|
final var rootScope = this.getRootScope();
|
||||||
|
configure.setDelegate(rootScope);
|
||||||
|
configure.call(rootScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S extends ComponentScope> void configureRootScope(
|
||||||
|
Class<S> scopeClass,
|
||||||
|
@ClosureParams(value = FirstParam.FirstGenericType.class)
|
||||||
|
@DelegatesTo(type = "S")
|
||||||
|
Closure<?> configure
|
||||||
|
) {
|
||||||
|
final var rootScope = this.getRootScope(scopeClass);
|
||||||
|
configure.setDelegate(rootScope);
|
||||||
|
configure.call(rootScope);
|
||||||
|
}
|
||||||
|
|
||||||
default ComponentScope getCurrentScope() {
|
default ComponentScope getCurrentScope() {
|
||||||
final List<ComponentScope> scopeStack = this.getScopeStack();
|
final List<ComponentScope> scopeStack = this.getScopeStack();
|
||||||
if (scopeStack.isEmpty()) {
|
if (scopeStack.isEmpty()) {
|
||||||
@ -37,6 +63,27 @@ public interface ComponentContext {
|
|||||||
return scopeClass.cast(this.getCurrentScope());
|
return scopeClass.cast(this.getCurrentScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void configureCurrentScope(
|
||||||
|
@ClosureParams(value = SimpleType.class, options = "groowt.view.component.context.ComponentScope")
|
||||||
|
@DelegatesTo(ComponentScope.class)
|
||||||
|
Closure<?> configure
|
||||||
|
) {
|
||||||
|
final var currentScope = this.getCurrentScope();
|
||||||
|
configure.setDelegate(currentScope);
|
||||||
|
configure.call(currentScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <S extends ComponentScope> void configureCurrentScope(
|
||||||
|
Class<S> scopeClass,
|
||||||
|
@ClosureParams(value = FirstParam.FirstGenericType.class)
|
||||||
|
@DelegatesTo(type = "S")
|
||||||
|
Closure<?> configure
|
||||||
|
) {
|
||||||
|
final var currentScope = this.getCurrentScope(scopeClass);
|
||||||
|
configure.setDelegate(currentScope);
|
||||||
|
configure.call(currentScope);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable ViewComponent getParent();
|
@Nullable ViewComponent getParent();
|
||||||
|
|
||||||
default <T extends ViewComponent> @Nullable T getParent(Class<T> parentClass) {
|
default <T extends ViewComponent> @Nullable T getParent(Class<T> parentClass) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package groowt.view.component.context;
|
package groowt.view.component.context;
|
||||||
|
|
||||||
import groowt.view.component.ViewComponent;
|
import groowt.view.component.ViewComponent;
|
||||||
|
import groowt.view.component.factory.ComponentFactories;
|
||||||
import groowt.view.component.factory.ComponentFactory;
|
import groowt.view.component.factory.ComponentFactory;
|
||||||
|
|
||||||
public interface ComponentScope {
|
public interface ComponentScope {
|
||||||
@ -11,6 +12,10 @@ public interface ComponentScope {
|
|||||||
|
|
||||||
<T extends ViewComponent> void add(String typeName, Class<T> forClass, ComponentFactory<? extends T> factory);
|
<T extends ViewComponent> void add(String typeName, Class<T> forClass, ComponentFactory<? extends T> factory);
|
||||||
|
|
||||||
|
default <T extends ViewComponent> void addWithNoArgConstructor(String typeName, Class<T> forClass) {
|
||||||
|
this.add(typeName, forClass, ComponentFactories.ofNoArgConstructor(forClass));
|
||||||
|
}
|
||||||
|
|
||||||
boolean contains(String typeName);
|
boolean contains(String typeName);
|
||||||
|
|
||||||
void remove(String typeName);
|
void remove(String typeName);
|
||||||
@ -34,6 +39,17 @@ public interface ComponentScope {
|
|||||||
ComponentFactory<? extends T> factory
|
ComponentFactory<? extends T> factory
|
||||||
);
|
);
|
||||||
|
|
||||||
|
default <T extends ViewComponent> void addWithNoArgConstructor(Class<T> forClass) {
|
||||||
|
this.add(forClass, ComponentFactories.ofNoArgConstructor(forClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T extends ViewComponent> void addWithNoArgConstructor(
|
||||||
|
Class<T> publicType,
|
||||||
|
Class<? extends T> implementingClass
|
||||||
|
) {
|
||||||
|
this.add(publicType, implementingClass, ComponentFactories.ofNoArgConstructor(implementingClass));
|
||||||
|
}
|
||||||
|
|
||||||
boolean contains(Class<? extends ViewComponent> type);
|
boolean contains(Class<? extends ViewComponent> type);
|
||||||
|
|
||||||
<T extends ViewComponent> TypeAndFactory<T> get(Class<T> type);
|
<T extends ViewComponent> TypeAndFactory<T> get(Class<T> type);
|
||||||
|
@ -22,6 +22,18 @@ public final class ComponentFactories {
|
|||||||
return (typeName, componentContext, args) -> supplier.get();
|
return (typeName, componentContext, args) -> supplier.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T extends ViewComponent> ComponentFactory<T> ofNoArgConstructor(
|
||||||
|
Class<? extends T> viewComponentClass
|
||||||
|
) {
|
||||||
|
return (typeName, componentContext, args) -> {
|
||||||
|
try {
|
||||||
|
return viewComponentClass.getConstructor().newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private ComponentFactories() {}
|
private ComponentFactories() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
package groowt.view.component.factory;
|
|
||||||
|
|
||||||
import groovy.lang.GroovyObjectSupport;
|
|
||||||
import groovy.lang.MetaClass;
|
|
||||||
import groovy.lang.MetaMethod;
|
|
||||||
import groovy.lang.MissingMethodException;
|
|
||||||
import groowt.view.component.context.ComponentContext;
|
|
||||||
import groowt.view.component.ViewComponent;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class can be used to create custom implementations {@link ComponentFactory}.
|
|
||||||
*
|
|
||||||
* @implSpec All implementations must simply provide one or more {@code doCreate()} methods,
|
|
||||||
* which will be found by this class via the Groovy meta object protocol. The method(s) may
|
|
||||||
* have any of the following signatures:
|
|
||||||
* <ul>
|
|
||||||
* <li>{@code String | Class, ComponentContext, ... -> T}</li>
|
|
||||||
* <li>{@code ComponentContext, ... -> T}</li>
|
|
||||||
* <li>{@code String | Class, ... -> T}</li>
|
|
||||||
* <li>{@code ... -> }</li>
|
|
||||||
* </ul>
|
|
||||||
* where '{@code ...}' represents zero or more additional arguments.
|
|
||||||
*
|
|
||||||
* @implNote In most cases, the implementation does not need to consume the
|
|
||||||
* {@link ComponentContext} argument, as the compiled template is required to contain
|
|
||||||
* {@code component.setContext(context)} statements following the component
|
|
||||||
* creation call. However, if the component <strong>needs</strong> the context
|
|
||||||
* (for example, to do custom scope logic), then it is more than okay to consume it.
|
|
||||||
*
|
|
||||||
* @implNote In the case Web View Components, the first additional argument will be
|
|
||||||
* a {@link Map} containing the attributes of the component, followed by any additional
|
|
||||||
* component constructor args.
|
|
||||||
*
|
|
||||||
* @param <T> The type of the ViewComponent produced by this factory.
|
|
||||||
*/
|
|
||||||
public abstract class ComponentFactoryBase<T extends ViewComponent> extends GroovyObjectSupport
|
|
||||||
implements ComponentFactory<T> {
|
|
||||||
|
|
||||||
protected static final String DO_CREATE = "doCreate";
|
|
||||||
|
|
||||||
protected static MetaMethod findDoCreateMethod(MetaClass metaClass, Class<?>[] types) {
|
|
||||||
return metaClass.getMetaMethod(DO_CREATE, types);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final Map<Class<?>[], MetaMethod> cache = new HashMap<>();
|
|
||||||
|
|
||||||
protected MetaMethod findDoCreateMethod(Object[] allArgs) {
|
|
||||||
return this.cache.computeIfAbsent(ComponentFactoryUtil.asTypes(allArgs), types ->
|
|
||||||
findDoCreateMethod(this.getMetaClass(), types)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected T findAndDoCreate(Object type, ComponentContext componentContext, Object[] args) {
|
|
||||||
final Object[] typeContextAndArgs = ComponentFactoryUtil.flatten(type, componentContext, args);
|
|
||||||
final MetaMethod typeContextAndArgsMethod = this.findDoCreateMethod(typeContextAndArgs);
|
|
||||||
if (typeContextAndArgsMethod != null) {
|
|
||||||
return (T) typeContextAndArgsMethod.invoke(this, typeContextAndArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object[] typeAndContext = new Object[] { type, componentContext };
|
|
||||||
final MetaMethod typeAndContextMethod = this.findDoCreateMethod(typeAndContext);
|
|
||||||
if (typeAndContextMethod != null) {
|
|
||||||
return (T) typeAndContextMethod.invoke(this, typeAndContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object[] typeAndArgs = ComponentFactoryUtil.flatten(type, args);
|
|
||||||
final MetaMethod typeAndArgsMethod = this.findDoCreateMethod(typeAndArgs);
|
|
||||||
if (typeAndArgsMethod != null) {
|
|
||||||
return (T) typeAndArgsMethod.invoke(this, typeAndArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object[] typeOnly = new Object[] { type };
|
|
||||||
final MetaMethod typeOnlyMethod = this.findDoCreateMethod(typeOnly);
|
|
||||||
if (typeOnlyMethod != null) {
|
|
||||||
return (T) typeOnlyMethod.invoke(this, typeOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Object[] contextOnly = new Object[] { componentContext };
|
|
||||||
final MetaMethod contextOnlyMethod = this.findDoCreateMethod(contextOnly);
|
|
||||||
if (contextOnlyMethod != null) {
|
|
||||||
return (T) contextOnlyMethod.invoke(this, contextOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
final MetaMethod argsOnlyMethod = this.findDoCreateMethod(args);
|
|
||||||
if (argsOnlyMethod != null) {
|
|
||||||
return (T) argsOnlyMethod.invoke(this, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new MissingMethodException(DO_CREATE, this.getClass(), args);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T create(String typeName, ComponentContext componentContext, Object... args) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this needs to be updated.
|
|
||||||
@Override
|
|
||||||
public T create(String alias, Class<?> type, ComponentContext componentContext, Object... args) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -20,7 +20,7 @@ public abstract class AbstractRenderContext implements RenderContext {
|
|||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComponentContext getComponentContext() {
|
protected ComponentContext getComponentContext() {
|
||||||
return this.componentContext;
|
return this.componentContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,10 @@ public interface ComponentWriter {
|
|||||||
|
|
||||||
void append(String string);
|
void append(String string);
|
||||||
void append(GString gString);
|
void append(GString gString);
|
||||||
void append(GString gString, int line, int column);
|
|
||||||
void append(ViewComponent viewComponent);
|
void append(ViewComponent viewComponent);
|
||||||
void append(ViewComponent viewComponent, int line, int column);
|
|
||||||
void append(Object object);
|
void append(Object object);
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
default void leftShift(Object object) {
|
default void leftShift(Object object) {
|
||||||
switch (object) {
|
switch (object) {
|
||||||
case String s -> this.append(s);
|
case String s -> this.append(s);
|
||||||
|
@ -58,32 +58,13 @@ public class DefaultComponentWriter implements ComponentWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void append(GString gString, int line, int column) {
|
public void append(ViewComponent viewComponent) {
|
||||||
final String content;
|
|
||||||
try {
|
try {
|
||||||
content = gString.toString();
|
|
||||||
} catch (Exception exception) {
|
|
||||||
throw new ComponentRenderException(line, column, exception);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
this.delegate.append(content);
|
|
||||||
} catch (IOException ioException) {
|
|
||||||
throw new RuntimeException(ioException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doComponentRender(ViewComponent viewComponent) throws IOException {
|
|
||||||
this.getRenderContext().pushComponent(viewComponent);
|
this.getRenderContext().pushComponent(viewComponent);
|
||||||
this.getComponentContext().pushDefaultScope();
|
this.getComponentContext().pushDefaultScope();
|
||||||
viewComponent.renderTo(this.delegate);
|
viewComponent.renderTo(this.delegate);
|
||||||
this.getComponentContext().popScope();
|
this.getComponentContext().popScope();
|
||||||
this.getRenderContext().popComponent(viewComponent);
|
this.getRenderContext().popComponent(viewComponent);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void append(ViewComponent viewComponent) {
|
|
||||||
try {
|
|
||||||
this.doComponentRender(viewComponent);
|
|
||||||
} catch (IOException ioException) {
|
} catch (IOException ioException) {
|
||||||
throw new RuntimeException(ioException);
|
throw new RuntimeException(ioException);
|
||||||
} catch (ComponentRenderException componentRenderException) {
|
} catch (ComponentRenderException componentRenderException) {
|
||||||
@ -93,19 +74,6 @@ public class DefaultComponentWriter implements ComponentWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void append(ViewComponent viewComponent, int line, int column) {
|
|
||||||
try {
|
|
||||||
this.doComponentRender(viewComponent);
|
|
||||||
} catch (IOException ioException) {
|
|
||||||
throw new RuntimeException(ioException);
|
|
||||||
} catch (ComponentRenderException componentRenderException) {
|
|
||||||
throw componentRenderException;
|
|
||||||
} catch (Exception exception) {
|
|
||||||
throw new ComponentRenderException(viewComponent, line, column, exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void append(Object object) {
|
public void append(Object object) {
|
||||||
switch (object) {
|
switch (object) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
---
|
---
|
||||||
import groowt.view.web.lib.Echo
|
import groowt.view.web.lib.Echo
|
||||||
---
|
---
|
||||||
<Echo greeting="Hello!"><p>${context}</p></Echo>
|
<Echo greeting=${cliGreeting}><p>$greeting</p></Echo>
|
||||||
|
@ -7,7 +7,7 @@ import org.codehaus.groovy.runtime.InvokerHelper
|
|||||||
|
|
||||||
import static groowt.view.web.WebViewComponentFactories.withAttr
|
import static groowt.view.web.WebViewComponentFactories.withAttr
|
||||||
|
|
||||||
class DefaultWebViewComponentScope extends DefaultComponentScope {
|
class DefaultWebViewComponentScope extends DefaultComponentScope implements WebViewComponentScope {
|
||||||
|
|
||||||
static DefaultWebViewComponentScope getDefaultRootScope() {
|
static DefaultWebViewComponentScope getDefaultRootScope() {
|
||||||
new DefaultWebViewComponentScope().tap {
|
new DefaultWebViewComponentScope().tap {
|
||||||
@ -15,6 +15,7 @@ class DefaultWebViewComponentScope extends DefaultComponentScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
<T extends WebViewComponent> void addWithAttr(Class<T> componentClass) {
|
<T extends WebViewComponent> void addWithAttr(Class<T> componentClass) {
|
||||||
add(componentClass, withAttr(componentClass) { attr ->
|
add(componentClass, withAttr(componentClass) { attr ->
|
||||||
InvokerHelper.invokeConstructorOf(componentClass, attr) as T
|
InvokerHelper.invokeConstructorOf(componentClass, attr) as T
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package groowt.view.web;
|
||||||
|
|
||||||
|
import groowt.view.component.context.ComponentScope;
|
||||||
|
|
||||||
|
public interface WebViewComponentScope extends ComponentScope {
|
||||||
|
<T extends WebViewComponent> void addWithAttr(Class<T> componentClass);
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package groowt.view.web
|
package groowt.view.web
|
||||||
|
|
||||||
import groowt.view.component.factory.ComponentFactories
|
|
||||||
import groowt.view.web.lib.AbstractWebViewComponentTests
|
import groowt.view.web.lib.AbstractWebViewComponentTests
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
@ -44,8 +43,8 @@ class BaseWebViewComponentTests extends AbstractWebViewComponentTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void nestedGreeter() {
|
void nestedGreeter() {
|
||||||
def context = this.context {
|
def context = this.context() {
|
||||||
getRootScope(DefaultWebViewComponentScope).with {
|
configureRootScope(WebViewComponentScope) {
|
||||||
addWithAttr(Greeter)
|
addWithAttr(Greeter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,9 +54,9 @@ class BaseWebViewComponentTests extends AbstractWebViewComponentTests {
|
|||||||
@Test
|
@Test
|
||||||
void doubleNested() {
|
void doubleNested() {
|
||||||
def context = this.context {
|
def context = this.context {
|
||||||
getRootScope(DefaultWebViewComponentScope).with {
|
configureRootScope(WebViewComponentScope) {
|
||||||
addWithAttr(Greeter)
|
addWithAttr(Greeter)
|
||||||
add(UsingGreeter, ComponentFactories.ofSupplier { new UsingGreeter() })
|
addWithNoArgConstructor(UsingGreeter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.doTest('<BaseWebViewComponentTests.UsingGreeter />', 'Hello, World!', context)
|
this.doTest('<BaseWebViewComponentTests.UsingGreeter />', 'Hello, World!', context)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package groowt.view.web.lib
|
package groowt.view.web.lib
|
||||||
|
|
||||||
import groowt.view.web.BaseWebViewComponent
|
import groowt.view.web.BaseWebViewComponent
|
||||||
import groowt.view.web.DefaultWebViewComponentScope
|
|
||||||
import groowt.view.web.WebViewComponentContext
|
import groowt.view.web.WebViewComponentContext
|
||||||
|
import groowt.view.web.WebViewComponentScope
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
class FragmentTests extends AbstractWebViewComponentTests {
|
class FragmentTests extends AbstractWebViewComponentTests {
|
||||||
@ -20,7 +20,7 @@ class FragmentTests extends AbstractWebViewComponentTests {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void configureContext(WebViewComponentContext context) {
|
void configureContext(WebViewComponentContext context) {
|
||||||
context.getRootScope(DefaultWebViewComponentScope).with {
|
context.configureRootScope(WebViewComponentScope) {
|
||||||
addWithAttr(Greeter)
|
addWithAttr(Greeter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package groowt.view.web.tools
|
package groowt.view.web.tools
|
||||||
|
|
||||||
|
import groowt.view.component.ComponentTemplate
|
||||||
import groowt.view.component.compiler.SimpleComponentTemplateClassFactory
|
import groowt.view.component.compiler.SimpleComponentTemplateClassFactory
|
||||||
import groowt.view.component.compiler.source.ComponentTemplateSource
|
import groowt.view.component.compiler.source.ComponentTemplateSource
|
||||||
import groowt.view.component.context.DefaultComponentContext
|
|
||||||
import groowt.view.component.runtime.DefaultComponentWriter
|
|
||||||
import groowt.view.web.BaseWebViewComponent
|
import groowt.view.web.BaseWebViewComponent
|
||||||
|
import groowt.view.web.DefaultWebViewComponentContext
|
||||||
import groowt.view.web.compiler.AnonymousWebViewComponent
|
import groowt.view.web.compiler.AnonymousWebViewComponent
|
||||||
import groowt.view.web.compiler.WebViewComponentTemplateCompileUnit
|
import groowt.view.web.compiler.WebViewComponentTemplateCompileUnit
|
||||||
import picocli.CommandLine
|
import picocli.CommandLine
|
||||||
@ -27,16 +27,15 @@ class RunTemplate implements Callable<Integer> {
|
|||||||
names = ['-A', '--attr', '--attribute'],
|
names = ['-A', '--attr', '--attribute'],
|
||||||
description = 'Attribute(s) to pass to the template.'
|
description = 'Attribute(s) to pass to the template.'
|
||||||
)
|
)
|
||||||
Map<String, String> properties
|
Map<String, String> attr
|
||||||
|
|
||||||
static class PropertiesComponent extends BaseWebViewComponent {
|
static class RunnableTemplate extends BaseWebViewComponent {
|
||||||
|
|
||||||
private final Map<String, String> properties
|
private final Map<String, String> cliAttr
|
||||||
|
|
||||||
@SuppressWarnings('GroovyAssignabilityCheck')
|
RunnableTemplate(Class<? extends ComponentTemplate> templateClass, Map<String, String> cliAttr) {
|
||||||
PropertiesComponent(Map<String, Object> attr) {
|
super(templateClass)
|
||||||
super('${renderChildren()}')
|
this.cliAttr = cliAttr
|
||||||
this.properties = attr.properties ?: [:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -44,7 +43,7 @@ class RunTemplate implements Callable<Integer> {
|
|||||||
try {
|
try {
|
||||||
return super.getProperty(propertyName)
|
return super.getProperty(propertyName)
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
return this.properties.get(propertyName)
|
return this.cliAttr.get(propertyName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,14 +60,12 @@ class RunTemplate implements Callable<Integer> {
|
|||||||
def compileResult = compileUnit.compile()
|
def compileResult = compileUnit.compile()
|
||||||
def templateLoader = new SimpleComponentTemplateClassFactory()
|
def templateLoader = new SimpleComponentTemplateClassFactory()
|
||||||
def templateClass = templateLoader.getTemplateClass(compileResult)
|
def templateClass = templateLoader.getTemplateClass(compileResult)
|
||||||
def template = templateClass.getConstructor().newInstance()
|
|
||||||
|
|
||||||
def context = new DefaultComponentContext()
|
def runnableTemplate = new RunnableTemplate(templateClass, this.attr)
|
||||||
context.pushDefaultScope()
|
def componentContext = new DefaultWebViewComponentContext()
|
||||||
|
runnableTemplate.context = componentContext
|
||||||
|
|
||||||
def componentWriter = new DefaultComponentWriter(new OutputStreamWriter(System.out))
|
println runnableTemplate.render()
|
||||||
|
|
||||||
template.renderer.call(context, componentWriter)
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user