/* * Copyright 2015 Mirosław Romaniuk (mi9rom@gmail.com) * * Licensed 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 com.vaadHL.window.base; import org.vaadin.dialogs.ConfirmDialog; import com.vaadHL.IAppContext; import com.vaadHL.utl.action.Action; import com.vaadHL.utl.action.Action.Command; import com.vaadHL.utl.action.ActionGroup; import com.vaadHL.utl.action.ActionsIds; import com.vaadHL.window.base.perm.IWinPermChecker; import com.vaadHL.window.customize.ICustomizeEditWin; import com.vaadHL.window.customize.ICustomizeLWMultiMode; import com.vaadHL.window.customize.ICustomizeEditWin.AutoSaveDiscard; import com.vaadHL.window.customize.ICustomizeWin; /** * Base editing form window. * * @author Miroslaw Romaniuk * */ public abstract class BaseEditWindow extends BaseWindow { private static final long serialVersionUID = 3045993334696013902L; private MWLaunchMode launchMode = null; private MWLaunchMode curWinMode = null; private boolean editingMode = false; private boolean readOnlyWin; private ICustomizeEditWin customize; protected ActionGroup crudActions; public BaseEditWindow(String winId, String caption, IWinPermChecker masterPermChecker, MWLaunchMode launchMode, IAppContext appContext, boolean readOnlyW, ICustomizeEditWin forceCustomize) { super(winId, caption, forceCustomize == null ? (ICustomizeWin) appContext .getWinCustomizerFactory().getCustomizer(winId) : forceCustomize, masterPermChecker, appContext); if (!approvedToOpen) return; this.customize = forceCustomize == null ? (ICustomizeEditWin) appContext .getWinCustomizerFactory().getCustomizer(winId) : forceCustomize; this.setReadOnlyWin(readOnlyW); curWinMode = this.launchMode = launchMode; if (isReadOnlyWin()) { if (launchMode == MWLaunchMode.VIEW_ONLY || launchMode == MWLaunchMode.EDIT || launchMode == MWLaunchMode.VIEW_EDIT) { curWinMode = this.launchMode = MWLaunchMode.VIEW_ONLY; } else { approvedToOpen = false; setNotPermitedContent(getWinId() + "VHL-015: " + getI18S("MVHL-015")); return; } if (isReadOnlyWin()) crudActions.setEnabled(false); } if (this.launchMode == MWLaunchMode.EDIT && !hasEditPerm()) { approvedToOpen = false; setNotPermitedContent(getWinId() + "VHL-016: " + getI18S("MVHL-016")); return; } else if (this.launchMode == MWLaunchMode.DELETE && !hasDeletePerm()) { approvedToOpen = false; setNotPermitedContent(getWinId() + "VHL-017: " + getI18S("MVHL-017")); return; } else if (this.launchMode == MWLaunchMode.NEW_REC && !hasCreatePerm()) { approvedToOpen = false; setNotPermitedContent(getWinId() + "VHL-018: " + getI18S("MVHL-018")); return; } } @Override protected void createActions() { super.createActions(); ActionGroup agCommit = new ActionGroup(ActionsIds.GAC_COMMIT); agCommit.put(new Action(getAppContext(), ActionsIds.AC_COMMIT_AND_CLOSE, new Command() { @Override public void run(Action action) { commitAndClose(); } }, true)); agCommit.put(new Action(getAppContext(), ActionsIds.AC_CANCEL_AND_CLOSE, new Command() { @Override public void run(Action action) { cancelAndClose(); } }, true)); agCommit.put(new Action(getAppContext(), ActionsIds.AC_SAVE_ASK_MSG, new Command() { @Override public void run(Action action) { saveAskMsg(null); } }, true)); agCommit.put(new Action(getAppContext(), ActionsIds.AC_DISCARD_ASK_MSG, new Command() { @Override public void run(Action action) { discardAskMsg(null); } }, true)); addActionsAndChkPerm(agCommit); ActionGroup newActions = new ActionGroup(ActionsIds.AC_BASE_EDIT_WIN); newActions.put(new Action(getAppContext(), ActionsIds.AC_DELETE, new Command() { @Override public void run(Action action) { deleteAskMsg(); } })); newActions.put(new Action(getAppContext(), ActionsIds.AC_CREATE, new Command() { @Override public void run(Action action) { createAskMsg(); } })); newActions.put(new Action(getAppContext(), ActionsIds.AC_EDIT, new Command() { @Override public void run(Action action) { toggleEditing(); } })); crudActions = newActions; addActionsAndChkPerm(newActions); } // ---------------- Window scope permission checking ------------ public boolean hasEditPerm() { if (launchMode == MWLaunchMode.VIEW_ONLY) return false; if (permChecker != null) return (permChecker.canEdit()); return true; } public boolean hasDeletePerm() { if (launchMode == MWLaunchMode.VIEW_ONLY) return false; if (permChecker != null) return (permChecker.canDelete()); return true; } public boolean hasCreatePerm() { if (launchMode == MWLaunchMode.VIEW_ONLY) return false; if (permChecker != null) return (permChecker.canCreate()); return true; } // ---------------- change checking ------------ /** * Checks if the content is not modified , and in the case it is, shows the * message to save or discard changes. * * @return true - there is no modification */ public boolean checkModifiedMsg() { if (isModified()) { showSaveDiscardMsg(); return false; } else return true; } /** * Checks the content modification state. * * @return true - there is at least one modification */ public abstract boolean isModified(); // ---------------- save , discard handling ------------ /** * Saves changes without any checks. * * @throws Exception */ abstract protected void save() throws Exception; /** * Validates the content before saving changes.<br> * Show a message or inform a user other way. * * @param showMessages * do show validation messages * @return true - OK */ public boolean validateSave(boolean showMessages) { return true; } /** * Saves changes with prior validation. * * @return true - saved */ public boolean saveChk() { if (!validateSave(true)) return false; return saveEInt(); } /** * Saves changes with exception interception. In case of error shows the * message. * * @return true - saved */ public boolean saveEInt() { try { save(); return true; } catch (RuntimeException re) { if (re.getCause() instanceof javax.persistence.OptimisticLockException || re.getCause() instanceof org.eclipse.persistence.exceptions.OptimisticLockException || re.getCause() instanceof com.vaadin.data.util.sqlcontainer.OptimisticLockException) getMsgs().showError("VHL-005: " + getI18S("MVHL-005")); else getMsgs().showError("VHL-006", re); return false; } catch (Exception e) { getMsgs().showError("VHL-007", e); return false; } } /** * Validates and saves changes with prior asking depending on customization * parameters. * * @param actionClose * the action to perform after successful saving. null - do * nothing */ public void saveAskMsg(final Runnable actionClose) { if (!validateSave(true)) return; if (isModified() && isAskSave()) { ConfirmDialog.show(getUI(), getI18S("SaveQ"), getI18S("Save_changesQ"), getI18S("btYes"), getI18S("btNo"), new Runnable() { @Override public void run() { if (saveChk()) if (actionClose != null) actionClose.run(); } }); } else if (saveEInt()) if (actionClose != null) actionClose.run(); } /** * Discards changes without any checks. */ protected void discard() throws Exception { if (launchMode == MWLaunchMode.NEW_REC) close(); } /** * Discards changes with exception interception. In case of error show the * message. * * @return true - saved */ public boolean discardEInt() { try { discard(); return true; } catch (Exception e) { getMsgs().showError("E001,e"); return false; } } /** * Validates the content before discarding changes. * * @return true - OK */ public boolean validateDiscard(boolean showMessages) { return true; } /** * Discards changes with prior validation. In case of error show the * message. * * @return true - discarded */ public boolean discardChk() { if (validateDiscard(true)) { return discardEInt(); } else return false; } /** * Validates and discards changes with behaviour depending on customization * parameters. * * @param actionClose * the action to perform after successful discarding. null - do * nothing */ public void discardAskMsg(final Runnable actionClose) { if (!validateDiscard(true)) return; if (isModified() && isAskDiscard()) { ConfirmDialog.show(getUI(), getI18S("DiscardQ"), getI18S("Discard_changesQ"), getI18S("btYes"), getI18S("btNo"), new Runnable() { @Override public void run() { if (discardChk()) if (actionClose != null) actionClose.run(); } }); } else if (discardChk()) if (actionClose != null) actionClose.run(); } /** * Validates, next saves or discards changes depending on customization * parameters. * * @param actionClose * the action to perform after successful saving or discarding. * null - do nothing */ protected void saveDiscardAction(final Runnable actionClose) { if (getAutoSaveDiscard() == AutoSaveDiscard.ASK) { ConfirmDialog.show(getUI(), getI18S("Unsaved_changes"), getI18S("Wtd_changes"), getI18S("btSave"), getI18S("btCancel"), getI18S("btDiscard"), new ConfirmDialog.Listener() { private static final long serialVersionUID = -8823586806134361654L; public void onClose(ConfirmDialog dialog) { if (dialog.isConfirmed()) { if (saveChk()) actionClose.run(); } else if (dialog.isCanceled()) { } else if (discardChk()) actionClose.run(); } }); return; } else if (getAutoSaveDiscard() == AutoSaveDiscard.SAVE) { if (saveChk()) actionClose.run(); } else if (getAutoSaveDiscard() == AutoSaveDiscard.DISCARD) { if (discardChk()) actionClose.run(); } else { showSaveDiscardMsg(); return; } } // ---------------- delete, create ------------ /** * Deletes the content without any checks. */ public void delete() { } /** * Checks other issues than validating content before performing deletion. * In case deletion is not allowed shows appropriate message. * * @return TRUE - can delete */ protected boolean canDeleteMsg() { return true; } /** * Validates and deletes the content with prior asking depending on * customization parameters. */ public void deleteAskMsg() { if (!canDeleteMsg()) return; if (isAskDelete()) ConfirmDialog.show(getUI(), getI18S("DeleteQ"), getI18S("Confirm_deleteQ"), getI18S("btYes"), getI18S("btNo"), new Runnable() { @Override public void run() { deleteIfNotMod(); } }); else deleteIfNotMod(); } /** * Deletes the content if there is no modification, otherwise show the * message. * * @return true - deletion performed */ public boolean deleteIfNotMod() { if (isModified()) { showSaveDiscardMsg(); return false; } else { delete(); return true; } } /** * Checks other issues than validating content and the form level permission * before switching to the new record mode. In case creation is not allowed * shows appropriate message. * * @return TRUE - can edit */ protected boolean canCreateMsg() { return true; } /** * Validates and creates the content with prior asking depending on * customization parameters. */ public void createAskMsg() { if (!canCreateMsg()) return; if (isAskCreate()) ConfirmDialog.show(getUI(), getI18S("CreateQ"), getI18S("Confirm_createQ"), getI18S("btYes"), getI18S("btNo"), new Runnable() { @Override public void run() { createIfNotMod(); } }); else createIfNotMod(); } /** * Creates a new content if there is no modification, otherwise show the * message. * * @return true - creation performed */ public boolean createIfNotMod() { if (isModified()) { showSaveDiscardMsg(); return false; } else { create(); return true; } } /** * Creates a new content ( eg. a new record). */ protected void create() { curWinMode = MWLaunchMode.NEW_REC; setEditModeChkMsg(true); } // ---------------- window closing ------------ /** * Validates and saves changes with prior asking depending on customization * parameters. Next closes the window. */ public void commitAndClose() { saveAskMsg(new Runnable() { @Override public void run() { close(); } }); } /** * Validates and discards changes with prior asking depending on * customization parameters. Next closes the window. */ public void cancelAndClose() { if (isModified()) discardAskMsg(new Runnable() { @Override public void run() { close(); } }); else close(); } /** * Closes the window with modification checking and actions depending on * customization parameters. */ @Override public void close() { if (!approvedToOpen) super.close(); else if (isModified()) { saveDiscardAction(new Runnable() { @Override public void run() { BaseEditWindow.super.close(); } }); } else super.close(); } public AutoSaveDiscard getAutoSaveDiscard() { return customize.getAutoSaveDiscard(); } public boolean isAskSave() { return customize.isAskSave(); } public boolean isAskDiscard() { return customize.isAskDiscard(); } public boolean isAskCreate() { return customize.isAskCreate(); } public boolean isAskDelete() { return customize.isAskDelete(); } public boolean isPrevNextFunc() { return customize.isPrevNextFunc(); } // ---------------- Edit mode ------------ /** * Enables or disables editing mode. Before changing the mode necessary * checks are performed. * * @param editMode * TRUE - set the editing mode otherwise set the viewing mode * @return TRUE - operation successful */ public boolean setEditModeChkMsg(boolean editMode) { if (editMode) return enableEditChkMsg(); else return disableEdit(); } /** * Disables editing. * * @return TRUE - edition disabled */ protected boolean disableEdit() { setEditingMode(false); return true; } /** * Checks other issues than validating content and the form level permission * before switching to the edit mode. In case edition is not allowed shows * appropriate message. * * @return TRUE - can edit */ protected boolean canEditMsg() { return true; } protected boolean enableEditChkMsg() { if (getCurWinMode() == MWLaunchMode.NEW_REC) return enableEdit(); else { if (!canEditMsg()) return false; else return enableEdit(); } } /** * Enables editing. * * @return TRUE - edition enabled */ protected boolean enableEdit() { setEditingMode(true); return true; } /** * Enables or disables editing mode. Before changing the mode necessary * checks are performed. If enabling fails performs disabling. * * @param editMode * TRUE - set the editing mode otherwise set the viewing mode * */ protected void setEditModeChkMsgAlways(boolean editMode) { if (editMode) { if (!setEditModeChkMsg(true)) setEditModeChkMsg(false); } else setEditModeChkMsg(false); } /** * Sets default editing state of the window. <br> * <b>Attention</b>: shouldn't be called before objects binding. */ protected void setDefaultEditingMode() { if (launchMode == MWLaunchMode.EDIT || launchMode == MWLaunchMode.NEW_REC) setEditModeChkMsgAlways(true); else setEditModeChkMsgAlways(false); } /** * Toggles the editing state of the window. */ protected void toggleEditing() { setEditModeChkMsg(!isEditingMode()); } // ---------------- others ------------ /** * Shows the message about to save or discard changes */ protected void showSaveDiscardMsg() { getMsgs().showInfo(getI18S("PlSavDisc")); } /** * Returns window read-only status. * * @return true - read-only */ public boolean isReadOnlyWin() { return readOnlyWin; } public void setReadOnlyWin(boolean readOnlyW) { this.readOnlyWin = readOnlyW; } public MWLaunchMode getLaunchMode() { return launchMode; } @SuppressWarnings("unused") private void setLaunchMode(MWLaunchMode launchMode) { this.launchMode = launchMode; } public MWLaunchMode getCurWinMode() { return curWinMode; } protected void setCurWinMode(MWLaunchMode curWinMode) { this.curWinMode = curWinMode; } public boolean isEditingMode() { return editingMode; } private void setEditingMode(boolean editingMode) { this.editingMode = editingMode; } }