/* * 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.mvp.presenters; import static java.util.Collections.singleton; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vaadin.data.Buffered; import com.vaadin.data.Item; import com.vaadin.data.fieldgroup.FieldGroup.CommitException; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import de.unioninvestment.eai.portal.portlet.crud.domain.events.ModeChangeEvent; import de.unioninvestment.eai.portal.portlet.crud.domain.events.ModeChangeEventHandler; import de.unioninvestment.eai.portal.portlet.crud.domain.events.SelectionEvent; import de.unioninvestment.eai.portal.portlet.crud.domain.events.SelectionEventHandler; import de.unioninvestment.eai.portal.portlet.crud.domain.model.ContainerBlob; 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.Dialog; import de.unioninvestment.eai.portal.portlet.crud.domain.model.Panel; import de.unioninvestment.eai.portal.portlet.crud.domain.model.Table; import de.unioninvestment.eai.portal.portlet.crud.domain.model.Table.DisplayMode; import de.unioninvestment.eai.portal.portlet.crud.domain.model.Table.Mode; import de.unioninvestment.eai.portal.portlet.crud.mvp.views.PanelContentView; import de.unioninvestment.eai.portal.portlet.crud.mvp.views.RowEditingFormView; /** * Presenter für das Formular zum editieren einer Tabellenzeile. * * * @author siva.selvarajah */ @SuppressWarnings("serial") public class RowEditingFormPresenter extends DialogPresenter implements RowEditingFormView.Presenter { private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory .getLogger(RowEditingFormView.class); private Panel parentPanel; private final String dialogId; private final Table table; private DataContainer container; ContainerRow currentContainerRow; /** * Konstruktor. * * @param view * View zum anzeigen des Forluars * @param model * Formular-Dialog-Modelklasse * @param parentPanel * Übergeordnetes Panle * @param dialogId * Eindeutiger Id des Dialogs * @param table * Tabellenmodel */ public RowEditingFormPresenter(PanelContentView view, Dialog model, Panel parentPanel, String dialogId, Table table) { super(view, model); this.parentPanel = parentPanel; this.dialogId = dialogId; this.table = table; this.container = table.getContainer(); initialize(); } @Override protected Button addBackButton(String caption) { Button button = super.addBackButton(caption); this.backButton = button; return button; } private void initialize() { getView().initialize(this, table); table.addModeChangeEventHandler(new ModeChangeEventHandler<Table, Table.Mode>() { @Override public void onModeChange(ModeChangeEvent<Table, Mode> event) { handleModeChange(event.getMode()); } }); table.addDisplayModeChangeEventHandler(new ModeChangeEventHandler<Table, Table.DisplayMode>() { @Override public void onModeChange(ModeChangeEvent<Table, DisplayMode> event) { handleDisplayModeChange(event.getSource().getDisplayMode()); } }); table.addSelectionEventHandler(new SelectionEventHandler() { @Override public void onSelectionChange(SelectionEvent selectionEvent) { handleSelectionChange(); } }); backButton.addClickListener(new ClickListener() { @Override public void buttonClick(ClickEvent event) { table.changeDisplayMode(DisplayMode.TABLE); } }); } protected void handleDisplayModeChange(DisplayMode displayMode) { if (displayMode == DisplayMode.FORM) { parentPanel.attachDialog(dialogId); updateButtonsForMode(table.getMode()); displayCurrentTableSelection(); } else { if (isAttached()) { parentPanel.detachDialog(); } } } protected void handleSelectionChange() { if (table.getDisplayMode() == DisplayMode.FORM) { displayCurrentTableSelection(); } } protected void handleModeChange(Mode mode) { if (table.getDisplayMode() == DisplayMode.FORM) { updateButtonsForMode(mode); displayCurrentRow(); } } private void displayCurrentTableSelection() { Set<ContainerRowId> selection = table.getSelection(); if (selection.size() == 1) { ContainerRow selectedRow = table.getContainer().getRow( selection.iterator().next(), false, true); displayRow(selectedRow); } } private void updateButtonsForMode(Mode mode) { if (mode == Mode.VIEW) { getView().updateButtonsForViewMode(); } else { getView().updateButtonsForEditMode(); } } @Override public void changeMode() { boolean success = trySave(); if (success) { table.changeMode(); } } @Override public void addLobFields(Item item) { ContainerRow containerRow = table.getContainer().convertItemToRow(item, false, false); for (String fieldName : getVisibleFields()) { if (container.isCLob(fieldName)) { boolean isReadOnly = isReadOnly(containerRow, fieldName); getView().addClobField(table.getColumns().get(fieldName), isReadOnly); } else if (container.isBLob(fieldName)) { ContainerBlob blob = container.getBLob(containerRow.getId(), fieldName); boolean isReadOnly = isReadOnly(containerRow, fieldName); getView().addBlobField(containerRow, table.getColumns().get(fieldName), blob, isReadOnly); } } } private boolean isReadOnly(ContainerRow containerRow, String fieldName) { boolean isReadOnly = containerRow.getFields().get(fieldName) .isReadonly() || !isTableRowEditable(containerRow); return isReadOnly; } private boolean isTableRowEditable(ContainerRow containerRow) { return table.getMode() == Mode.EDIT && table.isRowEditable(currentContainerRow); } private boolean isTableRowDeletable(ContainerRow containerRow) { return container.isDeleteable() && table.getMode() == Mode.EDIT && table.isRowDeletable(containerRow.getId()); } /** * Öffnet das Formular zum editieren der Zeile. * * @param currentContainerRow * Anzuzeigende Zeile */ public void displayRow(ContainerRow currentContainerRow) { if (currentContainerRow != null) { this.currentContainerRow = currentContainerRow; displayCurrentRow(); } } private void displayCurrentRow() { try { getView().hideFormError(); getView().displayRow(currentContainerRow, isTableRowEditable(currentContainerRow), isTableRowDeletable(currentContainerRow)); } catch (RuntimeException e) { table.changeDisplayMode(DisplayMode.TABLE); throw e; } } @Override public RowEditingFormView getView() { if (super.getView() instanceof RowEditingFormView) { return (RowEditingFormView) super.getView(); } else { throw new IllegalStateException("View ist kein " + RowEditingFormView.class.getSimpleName()); } } @Override public void save() { boolean success = trySave(); if (success) { table.changeDisplayMode(DisplayMode.TABLE); } } private boolean trySave() { try { List<String> modifiedFieldNames = getModifiedFieldNames(); Map<String, Object> modifiedColumnNames = getModifiedFieldValues(modifiedFieldNames); getView().commit(); try { fireRowChangeEvent(modifiedColumnNames); validateRow(); container.commit(); return true; } catch (Exception e) { LOG.error("Error during form commit: {}", e.getMessage()); getView().showFormError(e.getMessage()); return false; } } catch (Buffered.SourceException e) { String rootCauseMessage = ExceptionUtils.getRootCause(e) .getMessage(); LOG.error("Error during form commit: {}", rootCauseMessage); getView().showFormError(rootCauseMessage); return false; } catch (CommitException e) { String rootCauseMessage = ExceptionUtils.getRootCause(e) .getMessage(); LOG.error("Error during form commit: {}", rootCauseMessage); getView().showFormError(rootCauseMessage); return false; } catch (Exception e) { LOG.error("Error during form commit!", e); getView().showFormError(ExceptionUtils.getRootCause(e).toString()); return false; } } private void validateRow() { table.validateIfChanged(currentContainerRow.getId()); } private void fireRowChangeEvent(Map<String, Object> modifiedColumnNames) { if (modifiedColumnNames.size() > 0) { table.rowChange(currentContainerRow.getId(), modifiedColumnNames); } } /** * liefert eine Zuordnung zwischen Namen(key) der Felder mit Änderungen und * neuen Werten(value). * * @param modifiedFieldNames * Liste mit Namen der Felder, die geänderte Werte beinhalten. */ public Map<String, Object> getModifiedFieldValues( List<String> modifiedFieldNames) { Map<String, Object> fields = new HashMap<String, Object>(); for (String fieldName : modifiedFieldNames) { if (container.isCLob(fieldName)) { fields.put(fieldName, null); } else { fields.put(fieldName, currentContainerRow.getFields().get(fieldName) .getValue()); } } return fields; } /** * liefert eine Liste mit Namen der Felder, in den Änderungen vorgenommen * worden sind. */ public List<String> getModifiedFieldNames() { List<String> fields = new ArrayList<String>(); for (String fieldName : getVisibleFields()) { if (getView().isFieldModifed(fieldName)) { if (container.isCLob(fieldName)) { fields.add(fieldName); } else { fields.add(fieldName); } } } return fields; } @Override public List<String> getVisibleFields() { return table.getColumns().getVisibleNamesForForm(); } @Override public void delete() { ContainerRowId containerRowId = currentContainerRow.getId(); container.removeRows(singleton(containerRowId)); table.changeDisplayMode(DisplayMode.TABLE); } @Override public boolean hasPreviousRow() { return container.previousRowId(currentContainerRow.getId()) != null; } @Override public boolean hasNextRow() { return container.nextRowId(currentContainerRow.getId()) != null; } @Override public boolean nextRow() { ContainerRowId nextRowId = container.nextRowId(currentContainerRow .getId()); if (nextRowId != null) { switchToRow(nextRowId); return true; } return false; } @Override public boolean previousRow() { ContainerRowId previousRowId = container .previousRowId(currentContainerRow.getId()); if (previousRowId != null) { switchToRow(previousRowId); return true; } return false; } private void switchToRow(ContainerRowId otherRowId) { table.changeSelection(singleton(otherRowId)); } @Override public void resetFields() { getView().hideFormError(); getView().discard(); } @Override public void cancel() { table.changeDisplayMode(DisplayMode.TABLE); } }