/*
* 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.portlet.crud.scripting.model;
import groovy.lang.Closure;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.CommitEvent;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.CommitEventHandler;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.CreateEvent;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.CreateEventHandler;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.DeleteEvent;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.DeleteEventHandler;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.InsertEvent;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.InsertEventHandler;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.UpdateEvent;
import de.unioninvestment.eai.portal.portlet.crud.domain.events.UpdateEventHandler;
import de.unioninvestment.eai.portal.portlet.crud.domain.model.ContainerRow;
import de.unioninvestment.eai.portal.portlet.crud.domain.model.ContainerRowId;
import de.unioninvestment.eai.portal.portlet.crud.domain.model.DataContainer;
import de.unioninvestment.eai.portal.portlet.crud.domain.model.filter.Filter;
import groovy.lang.DelegatesTo;
/**
* Basisklasse für Container, die Event-Handler(onInsert, onCreate, onDelete,
* onUpdate, onCommit) in Form von Groovy-Skripten zur Verfügung stellen.
*/
public class ScriptContainer extends ScriptComponent {
protected DataContainer container;
private Closure<?> onInsert;
private Closure<?> onCreate;
private Closure<?> onDelete;
private Closure<?> onUpdate;
private Closure<?> onCommit;
public ScriptContainer(DataContainer container) {
super();
this.container = container;
}
/**
* @param closure
* eine Closure, in der die Methoden aus der
* {@link ScriptFilterFactory} direkt aufgerufen werden können,
* um Filter auf dem Container zu setzen.
*/
public void addFilters(@DelegatesTo(ScriptFilterFactory.class) Closure<?> closure) {
Object oldDelegate = closure.getDelegate();
try {
List<Filter> filters = new FilterClosureCallable(closure).call();
container.addFilters(filters);
} finally {
closure.setDelegate(oldDelegate);
}
}
/**
*
* @param closure
* eine Closure, in der die Methoden aus der
* {@link ScriptFilterFactory} direkt aufgerufen werden können,
* um Filter auf dem Container zu setzen.
*/
public void replaceFilters(@DelegatesTo(ScriptFilterFactory.class) Closure<?> closure) {
Object oldDelegate = closure.getDelegate();
try {
List<Filter> filters = new FilterClosureCallable(closure).call();
container.replaceFilters(filters, false);
} finally {
closure.setDelegate(oldDelegate);
}
}
/**
* @param namedArgs
* optional parameters, <code>timeout</code>: Timeout-Zeit in
* Sekunden
* @param closure
* eine Closure, in der die Methoden aus der
* {@link ScriptFilterFactory} direkt aufgerufen werden können,
* um Filter auf dem Container zu setzen.
*/
public void replaceFilters(Map<String, Object> namedArgs, @DelegatesTo(ScriptFilterFactory.class) Closure<?> closure) {
Object oldDelegate = closure.getDelegate();
try {
List<Filter> filters = new FilterClosureCallable(closure).call();
int timeout = extractTimeoutValue(namedArgs);
container.replaceFilters(filters, false, false, timeout);
} finally {
closure.setDelegate(oldDelegate);
}
}
private int extractTimeoutValue(Map<String, Object> namedArgs) {
int timeout = 0;
Object timeoutValue = namedArgs.get("timeout");
if (timeoutValue != null) {
if (timeoutValue instanceof Number) {
timeout = ((Number) timeoutValue).intValue();
} else {
throw new IllegalArgumentException(
"'timeout' needs to be of type Integer");
}
}
return timeout;
}
/**
* Entfernt alle auf dem Container gesetzten Filter (durable verbleiben)
*/
public void removeAllFilters() {
container.removeAllFilters();
}
/**
* Entfernt alle auf dem Container gesetzten Filter.
*
* @param removeDurable
* ob die durable-Filter auch mit entfernt werden sollen
*/
public void removeAllFilters(boolean removeDurable) {
container.removeAllFilters(removeDurable);
}
/**
* Iteriert durch alle Zeilen und führt für jede Zeile die Cosure aus.
*
* @param c
* Closure mit einem Parameter { ScriptRow row -> ... }, die für
* jede Zeile aufgerufen wird
*/
public void eachRow(final Closure<?> c) {
container.eachRow(new DataContainer.EachRowCallback() {
@Override
public void doWithRow(ContainerRow row) {
c.call(new ScriptRow(row));
}
});
}
/**
* Löschen aller Zeilen im Container die den aktuellen Filterkriterien
* entsprechen
*
* Bei großen Datenmengen inperformant, da die komplette gefilterte Tabelle
* eingelesen wird. Bitte in diesem Fall die Filter selbst auslesen und per
* sql()-API löschen
*/
public void removeAllRows() {
container.removeAllRows();
}
/**
* Fügt eine neue Zeile hinzu.
*
* @return Neue Zeile
*/
public ScriptRow addRow() {
ContainerRow row = container.addRow();
return new ScriptRow(row);
}
/**
* Liefert die {@link ScriptRowId}s aller in diesem Container enthaltenen
* Zeilen zurück.
*
* @return Liste der Ids
*/
public List<ScriptRowId> getRowIds() {
List<ScriptRowId> result = new ArrayList<ScriptRowId>();
for (ContainerRowId rowId : container.getRowIds()) {
result.add(new ScriptRowId(rowId));
}
return result;
}
/**
* Führt das übergebene Closure in einer neuen Transaktion aus.
*
* @param c
* Closure
*/
public void withTransaction(final Closure<?> c) {
container.withTransaction(new DataContainer.TransactionCallback<Object>() {
@Override
public Object doInTransaction() {
c.call();
return null;
}
});
}
/**
* Führt das übergebene Closure in einer bestehenden Transaktion aus.
*
* @param c
* Closure
*/
public void withExistingTransaction(final Closure<?> c) {
container.withExistingTransaction(new DataContainer.TransactionCallback<Object>() {
@Override
public Object doInTransaction() {
c.call();
return null;
}
});
}
/**
* @return Closure mit zwei Parametern { ScriptContainer it, ScriptRow row
* -> ... }, die nach dem Speichern einer neuen Zeile aufgerufen
* wird
*/
public Closure<?> getOnInsert() {
return onInsert;
}
/**
* @param onInsert
* Closure mit zwei Parametern { ScriptContainer it, ScriptRow
* row -> ... }, die nach dem Erstellen einer neuen Zeile
* aufgerufen wird
*/
public void setOnInsert(Closure<?> onInsert) {
this.onInsert = onInsert;
}
/**
* @return Closure mit zwei Parametern { ScriptContainer it, ScriptRow row
* -> ... }, die nach dem Erstellen einer neuen Zeile aufgerufen
* wird
*/
public Closure<?> getOnCreate() {
return onCreate;
}
/**
* @param onCreate
* Closure mit zwei Parametern { ScriptContainer it, ScriptRow
* row -> ... }, die nach dem Speichern einer neuen Zeile
* aufgerufen wird
*/
public void setOnCreate(Closure<?> onCreate) {
this.onCreate = onCreate;
}
/**
* @return Closure mit zwei Parametern { ScriptContainer it, ScriptRow row
* -> ... }, die nach dem Löschen einer Zeile aufgerufen wird
*/
public Closure<?> getOnDelete() {
return onDelete;
}
/**
* @param onDelete
* Closure mit zwei Parametern { ScriptContainer it, ScriptRow
* row -> ... }, die nach dem Löschen einer Zeile aufgerufen wird
*/
public void setOnDelete(Closure<?> onDelete) {
this.onDelete = onDelete;
}
/**
* @return Closure mit zwei Parametern { ScriptContainer it, ScriptRow row
* -> ... }, die nach dem Update einer Zeile aufgerufen wird
*/
public Closure<?> getOnUpdate() {
return onUpdate;
}
/**
* @param onUpdate
* Closure mit zwei Parametern { ScriptContainer it, ScriptRow
* row -> ... }, die nach dem Update einer Zeile aufgerufen wird
*/
public void setOnUpdate(Closure<?> onUpdate) {
this.onUpdate = onUpdate;
}
/**
* @return Closure mit dem Parameter { ScriptContainer it -> ... }, die nach
* einem Commit aufgerufen wird.
*/
public Closure<?> getOnCommit() {
return onCommit;
}
/**
* Committed alle Änderungen des Containers bzw. in gerade editierten
* Änderungen der Tabelle in die Datenbank
*/
public void commit() {
container.commit();
}
/**
* @param onCommit
* Closure mit dem Parameter { ScriptContainer it -> ... }, die
* nach einem Commit aufgerufen wird.
*/
public void setOnCommit(Closure<?> onCommit) {
this.onCommit = onCommit;
}
protected void initializeEventHandler() {
container.addInsertEventHandler(new InsertEventHandler() {
private static final long serialVersionUID = 1L;
@Override
public void onInsert(InsertEvent event) {
if (onInsert != null) {
onInsert.call(ScriptContainer.this,
createScriptRow(event.getRow()));
}
}
});
container.addCreateEventHandler(new CreateEventHandler() {
private static final long serialVersionUID = 1L;
@Override
public void onCreate(CreateEvent event) {
if (onCreate != null) {
onCreate.call(ScriptContainer.this,
createScriptRow(event.getRow()));
}
}
});
container.addDeleteEventHandler(new DeleteEventHandler() {
private static final long serialVersionUID = 1L;
@Override
public void onDelete(DeleteEvent event) {
if (onDelete != null) {
onDelete.call(ScriptContainer.this,
createScriptRow(event.getRow()));
}
}
});
container.addCommitEventHandler(new CommitEventHandler() {
private static final long serialVersionUID = 1L;
@Override
public void onCommit(CommitEvent event) {
if (onCommit != null) {
onCommit.call(ScriptContainer.this);
}
}
});
container.addUpdateEventHandler(new UpdateEventHandler() {
private static final long serialVersionUID = 1L;
@Override
public void onUpdate(UpdateEvent event) {
if (onUpdate != null) {
onUpdate.call(ScriptContainer.this,
createScriptRow(event.getRow()));
}
}
});
}
private ScriptRow createScriptRow(ContainerRow row) {
return new ScriptRow(row);
}
/**
* Aktualisiert die Daten auf der Tabelle.
*/
public void refresh() {
container.refresh();
}
DataContainer getContainer() {
return container;
}
}