/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package de.unioninvestment.eai.portal.support.scripting;
import com.vaadin.ui.Button;
import de.unioninvestment.eai.portal.portlet.crud.config.*;
import de.unioninvestment.eai.portal.portlet.crud.domain.exception.BusinessException;
import de.unioninvestment.eai.portal.portlet.crud.domain.model.ModelSupport;
import de.unioninvestment.eai.portal.portlet.crud.scripting.model.ScriptPortlet;
import de.unioninvestment.eai.portal.portlet.crud.scripting.model.ScriptRow;
import de.unioninvestment.eai.portal.portlet.crud.scripting.model.ScriptTab;
import de.unioninvestment.eai.portal.portlet.crud.scripting.model.ScriptTabs;
import de.unioninvestment.eai.portal.support.vaadin.groovy.VaadinBuilder;
import groovy.lang.Closure;
import groovy.lang.Script;
import org.junit.Before;
import org.junit.Test;
import org.mockito.internal.matchers.InstanceOf;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.xml.sax.SAXException;
import javax.xml.bind.JAXBException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.contains;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.startsWith;
import static org.mockito.Mockito.*;
@ContextConfiguration({ "/eai-portal-web-test-applicationcontext.xml" })
public class ConfigurationScriptsCompilerTest extends ModelSupport {
private ScriptCompiler scriptCompilerMock = mock(ScriptCompiler.class);
private ConfigurationScriptsCompiler compiler;
@Before
public void setUp() {
compiler = new ConfigurationScriptsCompiler(scriptCompilerMock);
}
@Test
public void shouldCompileExistingScript() throws JAXBException,
SAXException, ScriptingException {
PortletConfig portletConfig = createConfiguration("validScriptConfig.xml");
compiler.compileAllScripts(portletConfig);
verify(scriptCompilerMock)
.compileScript(
"log.info \"Hello World\"\nlog.debug 'MainPortletScript.groovy execution finished...'",
"MainPortletScript.groovy");
}
@Test
public void shouldCompileScriptsWithSrcAttribute() throws JAXBException,
SAXException, ScriptingException {
PortletConfig portletConfig = createConfiguration("validMultiScriptConfig.xml");
compiler.compileAllScripts(portletConfig);
verify(scriptCompilerMock).compileScript(
contains("log.info \"Hello Shared\""), eq("shared.groovy"));
verify(scriptCompilerMock).compileScript(
contains("log.info \"Hello Main\""),
eq("MainPortletScript.groovy"));
}
@Test
public void shouldCompileEmptyScriptIfNothingConfigured()
throws JAXBException, SAXException, ScriptingException {
PortletConfig portletConfig = createConfiguration("validConfig.xml");
compiler.compileAllScripts(portletConfig);
verify(scriptCompilerMock).compileScript("");
}
@Test
public void shouldCompileClosureScripts() throws JAXBException,
SAXException, ScriptingException {
PortletConfig portletConfig = createConfiguration("validTableActionConfig.xml");
compiler.compileAllScripts(portletConfig);
verify(scriptCompilerMock)
.compileScript(
"def aufruf() { println \"aufruf erfolgreich\" }\nlog.debug 'MainPortletScript.groovy execution finished...'",
"MainPortletScript.groovy");
verify(scriptCompilerMock).compileScript("{ it -> aufruf() }");
// assertThat(config.getScript().getValue().getClazz(), notNullValue());
}
@Test
public void shouldCompileAllClosureScripts() throws JAXBException,
SAXException, ScriptingException, InstantiationException,
IllegalAccessException {
ScriptCompiler scriptCompiler = new ScriptCompiler();
PortletConfig portletConfig = createConfiguration("validAllClosuresConfig.xml");
new ConfigurationScriptsCompiler(scriptCompiler)
.compileAllScripts(portletConfig);
assertThat(portletConfig.getOnRefresh().getClazz(), notNullValue());
assertThat(portletConfig.getOnLoad().getClazz(), notNullValue());
assertThat(portletConfig.getOnReload().getClazz(), notNullValue());
assertThat(getTabs(portletConfig).getOnChange().getClazz(),
notNullValue());
assertThat(getTab(portletConfig).getOnShow().getClazz(), notNullValue());
assertThat(getTab(portletConfig).getOnHide().getClazz(), notNullValue());
assertThat(getTable(portletConfig).getOnModeChange().getClazz(),
notNullValue());
assertThat(getTable(portletConfig).getOnSelectionChange().getClazz(),
notNullValue());
assertThat(getTable(portletConfig).getOnRowChange().getClazz(),
notNullValue());
assertThat(getTable(portletConfig).getRowEditable().getClazz(),
notNullValue());
assertThat(getTable(portletConfig).getRowDeletable().getClazz(),
notNullValue());
assertThat(getTable(portletConfig).getRowValidator().getClazz(),
notNullValue());
assertThat(getTable(portletConfig).getColumns().getColumn().get(2)
.getDefault().getClazz(), notNullValue());
assertThat(getTable(portletConfig).getColumns().getColumn().get(1)
.getValidator().getClazz(), notNullValue());
assertThat(getTable(portletConfig).getColumns().getColumn().get(9)
.getGenerator().getClazz(), notNullValue());
assertThat(getTable(portletConfig).getColumns().getColumn().get(9)
.getGeneratedValue().getClazz(), notNullValue());
assertThat(getTableAction(portletConfig).getOnExecution().getClazz(),
notNullValue());
assertThat(getTableActions(portletConfig).get(1).getExport()
.getFilename().getClazz(), notNullValue());
assertThat(getTableActions(portletConfig).get(2).getDownload()
.getGenerator().getClazz(), notNullValue());
assertThat(getFormAction(portletConfig).getOnExecution().getClazz(),
notNullValue());
assertThat(getFormField(portletConfig).getOnValueChange().getClazz(),
notNullValue());
assertThat(getDatabaseQuery(portletConfig).getOnCreate().getClazz(),
notNullValue());
assertThat(getDatabaseQuery(portletConfig).getOnDelete().getClazz(),
notNullValue());
assertThat(getDatabaseQuery(portletConfig).getOnInsert().getClazz(),
notNullValue());
assertThat(getDatabaseQuery(portletConfig).getOnUpdate().getClazz(),
notNullValue());
assertThat(getDatabaseQuery(portletConfig).getInsert().getStatement()
.getClazz(), notNullValue());
assertThat(getDatabaseQuery(portletConfig).getUpdate().getStatement()
.getClazz(), notNullValue());
assertThat(getDatabaseQuery(portletConfig).getDelete().getStatement()
.getClazz(), notNullValue());
assertThat(getComponentInCompoundSearch(portletConfig).getGenerator()
.getClazz(), notNullValue());
// TODO add missing closures
assertScriptExecution(portletConfig);
}
private ScriptComponentConfig getComponentInCompoundSearch(
PortletConfig portletConfig) {
CompoundSearchConfig search = (CompoundSearchConfig) portletConfig
.getPage().getElements().get(0);
return (ScriptComponentConfig) search.getDetails().getElements().get(0);
}
@Test
public void shouldCompileClosureScriptDynamicDropDown()
throws JAXBException, SAXException, ScriptingException,
InstantiationException, IllegalAccessException {
ScriptCompiler scriptCompiler = new ScriptCompiler();
PortletConfig portletConfig = createConfiguration("validDynamicDropDownConfig.xml");
new ConfigurationScriptsCompiler(scriptCompiler)
.compileAllScripts(portletConfig);
assertThat(getDynamicSelect(portletConfig).getDynamic().getOptions()
.getClazz(), notNullValue());
Script script = portletConfig.getScript().get(0).getValue().getClazz()
.newInstance();
script.getBinding()
.setVariable(
"log",
LoggerFactory
.getLogger(ConfigurationScriptsCompilerTest.class));
script.run();
Script dynamicClosureScript = getDynamicSelect(portletConfig)
.getDynamic().getOptions().getClazz().newInstance();
@SuppressWarnings("unchecked")
Closure<List<Integer>> dynamicClosure = (Closure<List<Integer>>) dynamicClosureScript
.run();
dynamicClosure.setDelegate(script);
ScriptRow scriptRowMock = mock(ScriptRow.class);
java.util.List<Integer> ret = dynamicClosure.call(scriptRowMock, null);
assertThat(ret.get(1), is(Integer.class));
verify(scriptRowMock).getValues();
}
@Test
public void shouldCompileComponentGeneratorScript() throws JAXBException {
ScriptCompiler scriptCompiler = new ScriptCompiler();
PortletConfig portletConfig = createConfiguration("validCustomComponentConfig.xml");
new ConfigurationScriptsCompiler(scriptCompiler)
.compileAllScripts(portletConfig);
ScriptComponentConfig scriptComponentConfig = (ScriptComponentConfig) portletConfig
.getPage().getElements().get(0);
assertThat(scriptComponentConfig.getGenerator().getClazz(),
notNullValue());
}
@Test
public void shouldCompileCustomFilterScript() throws JAXBException {
ScriptCompiler scriptCompiler = new ScriptCompiler();
PortletConfig portletConfig = createConfiguration("validScriptContainerConfig.xml");
new ConfigurationScriptsCompiler(scriptCompiler)
.compileAllScripts(portletConfig);
FormConfig formConfig = (FormConfig) portletConfig.getPage()
.getElements().get(0);
FormActionConfig actionConfig = formConfig.getAction().get(0);
List<FilterConfig> filters = actionConfig.getSearch().getApplyFilters()
.getFilters();
List<FilterConfig> nestedFilters = ((AnyFilterConfig) filters.get(0))
.getFilters();
CustomFilterConfig customFilterConfig = (CustomFilterConfig) nestedFilters
.get(nestedFilters.size() - 1);
assertThat(customFilterConfig.getFilter().getClazz(), notNullValue());
}
@Test
public void shouldCompileCustomFilterScriptInSubfilters()
throws JAXBException {
ScriptCompiler scriptCompiler = new ScriptCompiler();
PortletConfig portletConfig = createConfiguration("validScriptContainerConfig.xml");
new ConfigurationScriptsCompiler(scriptCompiler)
.compileAllScripts(portletConfig);
FormConfig formConfig = (FormConfig) portletConfig.getPage()
.getElements().get(0);
FormActionConfig actionConfig = formConfig.getAction().get(0);
List<FilterConfig> filters = actionConfig.getSearch().getApplyFilters()
.getFilters();
AnyFilterConfig anyFilterConfig = (AnyFilterConfig) filters.get(0);
CustomFilterConfig customFilterConfig = (CustomFilterConfig) anyFilterConfig
.getFilters().get(anyFilterConfig.getFilters().size() - 1);
assertThat(customFilterConfig.getFilter().getClazz(), notNullValue());
}
@Test
public void shouldReturnScriptComponentButton() throws JAXBException,
InstantiationException, IllegalAccessException {
ScriptCompiler scriptCompiler = new ScriptCompiler();
PortletConfig portletConfig = createConfiguration("validCustomComponentConfig.xml");
new ConfigurationScriptsCompiler(scriptCompiler)
.compileAllScripts(portletConfig);
ScriptComponentConfig scriptComponentConfig = (ScriptComponentConfig) portletConfig
.getPage().getElements().get(0);
Script generatorScript = scriptComponentConfig.getGenerator()
.getClazz().newInstance();
Closure<?> generatorClosure = (Closure<?>) generatorScript.run();
Script mainScript = portletConfig.getScript().get(0).getValue()
.getClazz().newInstance();
generatorClosure.setDelegate(mainScript);
Object result = generatorClosure.call(new VaadinBuilder());
assertThat(result, new InstanceOf(Button.class));
}
@Test
public void shouldCompileTableStyleClosures() throws JAXBException,
InstantiationException, IllegalAccessException {
ScriptCompiler scriptCompiler = new ScriptCompiler();
PortletConfig portletConfig = createConfiguration("validTableStyleConfig.xml");
new ConfigurationScriptsCompiler(scriptCompiler)
.compileAllScripts(portletConfig);
Script mainScript = portletConfig.getScript().get(0).getValue()
.getClazz().newInstance();
TableConfig tableConfig = (TableConfig) portletConfig.getPage()
.getElements().get(0);
assertThat(tableConfig.getRowStyle().getClazz(), notNullValue());
Script rowScript = tableConfig.getRowStyle().getClazz().newInstance();
@SuppressWarnings("unchecked")
Closure<String> rowClosure = (Closure<String>) rowScript.run();
rowClosure.setDelegate(mainScript);
ScriptRow scriptRowMock = mock(ScriptRow.class);
String rowResult = rowClosure.call(scriptRowMock);
assertThat(rowResult, is("rowStyle"));
assertThat(tableConfig.getColumns().getColumn().size(), is(1));
int j = 0;
for (ColumnConfig columnConfig : tableConfig.getColumns().getColumn()) {
assertThat(columnConfig.getStyle().getClazz(), notNullValue());
Script columnScript = columnConfig.getStyle().getClazz()
.newInstance();
@SuppressWarnings("unchecked")
Closure<String> columnClosure = (Closure<String>) columnScript
.run();
columnClosure.setDelegate(mainScript);
String columnResult = columnClosure.call(scriptRowMock,
"columnName" + j);
assertThat(columnResult, is("style-columnName" + j));
j++;
}
}
@Test
public void shouldShowScriptPositionOnScriptErrors() throws JAXBException,
SAXException, ScriptingException {
PortletConfig portletConfig = createConfiguration("validScriptConfig.xml");
when(
scriptCompilerMock
.compileScript(
"log.info \"Hello World\"\nlog.debug 'MainPortletScript.groovy execution finished...'",
"MainPortletScript.groovy")).thenThrow(
new ScriptingException(null,
"portlet.crud.error.compilingScript"));
try {
compiler.compileAllScripts(portletConfig);
fail();
} catch (BusinessException e) {
assertThat(e.getCode(), is("portlet.crud.error.compilingScript"));
}
}
@Test
public void shouldCompileGStringDefaultColumnValue() throws JAXBException,
InstantiationException, IllegalAccessException {
ScriptCompiler scriptCompiler = new ScriptCompiler();
PortletConfig portletConfig = createConfiguration("validDefaultColumnValueConfig.xml");
new ConfigurationScriptsCompiler(scriptCompiler)
.compileAllScripts(portletConfig);
Script mainScript = portletConfig.getScript().get(0).getValue()
.getClazz().newInstance();
TableConfig tableConfig = (TableConfig) portletConfig.getPage()
.getElements().get(0);
assertThat(tableConfig.getColumns().getColumn().get(2).getDefault()
.getClazz(), notNullValue());
Script defaulValueScript = tableConfig.getColumns().getColumn().get(2)
.getDefault().getClazz().newInstance();
Closure<?> defaultValueClosure = (Closure<?>) defaulValueScript.run();
defaultValueClosure.setDelegate(mainScript);
Date dt = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String datumString = df.format(dt);
Object object = defaultValueClosure.call(datumString);
assertThat(object.toString(), is(datumString));
}
@Test
public void shouldCompileStatementClosure() throws JAXBException,
InstantiationException, IllegalAccessException {
PortletConfig portletConfig = createConfiguration("validScriptCrudConfig.xml");
compiler.compileAllScripts(portletConfig);
verify(scriptCompilerMock).compileScript(contains("def doInsert(row)"),
eq("MainPortletScript.groovy"));
verify(scriptCompilerMock).compileScript(contains("doInsert(row) //"));
verify(scriptCompilerMock).compileScript(contains("doUpdate(row) //"));
verify(scriptCompilerMock).compileScript(contains("doDelete(row) //"));
}
@Test
public void shouldCompileScriptContainerDelegate() throws JAXBException {
PortletConfig portletConfig = createConfiguration("validScriptContainerConfig.xml");
compiler.compileAllScripts(portletConfig);
verify(scriptCompilerMock, times(3)).compileScript(anyString());
}
@Test
public void shouldCompileReSTContainerScripts() throws JAXBException {
PortletConfig portletConfig = createConfiguration("validReSTContainerFullXmlConfig.xml");
when(scriptCompilerMock.compileScript(anyString())).thenReturn(
Script.class);
compiler.compileAllScripts(portletConfig);
TableConfig tableConfig = (TableConfig) portletConfig.getPage()
.getElements().get(0);
ReSTContainerConfig container = tableConfig.getRestContainer();
List<ReSTAttributeConfig> attributes = container.getQuery()
.getAttribute();
assertScriptCompiled(container.getQuery().getCollection());
assertScriptCompiled(attributes.get(0).getPath());
assertScriptCompiled(attributes.get(1).getPath());
assertScriptCompiled(attributes.get(2).getPath());
assertScriptCompiled(container.getInsert().getValue());
assertScriptCompiled(container.getInsert().getUrl());
assertScriptCompiled(container.getUpdate().getValue());
assertScriptCompiled(container.getUpdate().getUrl());
assertScriptCompiled(container.getDelete().getUrl());
}
private void assertScriptCompiled(GroovyScript collection) {
assertThat(collection.getClazz(), notNullValue());
}
@Test
public void shouldCompileSqlStatementGString() throws JAXBException,
InstantiationException, IllegalAccessException {
PortletConfig portletConfig = createConfiguration("validQueryConfig.xml");
compiler.compileAllScripts(portletConfig);
verify(scriptCompilerMock).compileScript("");
verify(scriptCompilerMock, times(3)).compileScript(
startsWith("{ container,row,connection -> \"\"\""));
}
@Test
public void shouldCompileSimpleCompoundSearch() throws JAXBException,
InstantiationException, IllegalAccessException {
PortletConfig portletConfig = createConfiguration("validCompoundSearchSimpleConfig.xml");
compiler.compileAllScripts(portletConfig);
}
private SelectConfig getDynamicSelect(PortletConfig portletConfig) {
ColumnsConfig columns = ((TableConfig) portletConfig.getPage()
.getElements().get(0)).getColumns();
for (ColumnConfig cfg : columns.getColumn()) {
if (cfg.getSelect() != null && cfg.getSelect().getDynamic() != null) {
return cfg.getSelect();
}
}
return null;
}
private void assertScriptExecution(PortletConfig portletConfig)
throws InstantiationException, IllegalAccessException {
// mocking
ScriptPortlet portletMock = mock(ScriptPortlet.class);
ScriptTabs tabsMock = mock(ScriptTabs.class);
ScriptTab tabMock = mock(ScriptTab.class);
ScriptTab tabMock2 = mock(ScriptTab.class);
Map<String, ScriptTab> elements = new LinkedHashMap<String, ScriptTab>();
elements.put("tab1", tabMock);
elements.put("tab2", tabMock2);
when(portletMock.getTabs()).thenReturn(tabsMock);
when(tabsMock.getElements()).thenReturn(elements);
when(tabsMock.getActiveTab()).thenReturn(tabMock);
when(tabMock.getId()).thenReturn("tab1");
Script script = portletConfig.getScript().get(0).getValue().getClazz()
.newInstance();
script.getBinding().setVariable("portlet", portletMock);
script.getBinding()
.setVariable(
"log",
LoggerFactory
.getLogger(ConfigurationScriptsCompilerTest.class));
script.run();
@SuppressWarnings("unchecked")
Closure<ScriptTab> closure = ((Closure<ScriptTab>) getTabs(
portletConfig).getOnChange().getClazz().newInstance().run());
closure.setDelegate(script);
}
private TabsConfig getTabs(PortletConfig portletConfig) {
return (TabsConfig) portletConfig.getPage().getElements().get(2);
}
private TabConfig getTab(PortletConfig portletConfig) {
return getTabs(portletConfig).getTab().get(0);
}
private TableConfig getTable(PortletConfig portletConfig) {
return ((TableConfig) getTab(portletConfig).getElements().get(0));
}
private FormConfig getForm(PortletConfig portletConfig) {
return (FormConfig) portletConfig.getPage().getElements().get(1);
}
private FormActionConfig getFormAction(PortletConfig portletConfig) {
return getForm(portletConfig).getAction().get(0);
}
private FormFieldConfig getFormField(PortletConfig portletConfig) {
return getForm(portletConfig).getField().get(0);
}
private TableActionConfig getTableAction(PortletConfig portletConfig) {
return getTableActions(portletConfig).get(0);
}
private List<TableActionConfig> getTableActions(PortletConfig portletConfig) {
return getTable(portletConfig).getAction();
}
private DatabaseQueryConfig getDatabaseQuery(PortletConfig portletConfig) {
return getTable(portletConfig).getDatabaseQuery();
}
}