edu.ku.brc.specify.ui.DBObjDialogFactory.java Source code

Java tutorial

Introduction

Here is the source code for edu.ku.brc.specify.ui.DBObjDialogFactory.java

Source

/* Copyright (C) 2015, University of Kansas Center for Research
 * 
 * Specify Software Project, specify@ku.edu, Biodiversity Institute,
 * 1345 Jayhawk Boulevard, Lawrence, Kansas, 66045, USA
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package edu.ku.brc.specify.ui;

import static edu.ku.brc.helpers.XMLHelper.getAttr;

import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Window;
import java.util.Hashtable;
import java.util.Iterator;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Element;

import edu.ku.brc.af.core.AppContextMgr;
import edu.ku.brc.af.core.db.DBTableIdMgr;
import edu.ku.brc.af.core.db.DBTableInfo;
import edu.ku.brc.af.ui.ViewBasedDialogFactoryIFace;
import edu.ku.brc.af.ui.db.ViewBasedDisplayActionAdapter;
import edu.ku.brc.af.ui.db.ViewBasedDisplayDialog;
import edu.ku.brc.af.ui.db.ViewBasedDisplayFrame;
import edu.ku.brc.af.ui.db.ViewBasedDisplayIFace;
import edu.ku.brc.af.ui.db.ViewBasedSearchDialogIFace;
import edu.ku.brc.af.ui.forms.MultiView;
import edu.ku.brc.af.ui.forms.persist.ViewIFace;
import edu.ku.brc.exceptions.ConfigurationException;
import edu.ku.brc.specify.config.SpecifyAppContextMgr;
import edu.ku.brc.specify.datamodel.SpTaskSemaphore;
import edu.ku.brc.specify.datamodel.SpecifyUser;
import edu.ku.brc.specify.datamodel.busrules.BaseTreeBusRules;
import edu.ku.brc.specify.dbsupport.TaskSemaphoreMgr;
import edu.ku.brc.specify.dbsupport.TaskSemaphoreMgr.SCOPE;
import edu.ku.brc.specify.dbsupport.TaskSemaphoreMgr.USER_ACTION;
import edu.ku.brc.ui.UIRegistry;

/**
 * This class is the implementation for the ViewBasedDialogFactoryIFace interface for the entire application.
 * <BR><BR>
 * This class reads in dialog/frame definitions from dialog_defs.xml, there are two types of dialog: "search" and "display".
 * Certain UI components use this factory to create dialogs (modal or non-modal) for searching or displaying child objects.
 * <BR><BR>
 * For example, the TextWithInfo or the ComboBoxFromQuery has buttons that enables the user to pop up a dialog for displaying the current object in the control,
 * or to pop up a search dialog for locating (more precisely the object they desire.
 *
 * @code_status Beta
 * 
 * @author rods
 *
 */
public class DBObjDialogFactory implements ViewBasedDialogFactoryIFace {
    private static final Logger log = Logger.getLogger(DBObjDialogFactory.class);

    public static final String factoryName = "edu.ku.brc.specify.ui.DBObjDialogFactory"; //$NON-NLS-1$

    public enum FormLockStatus {
        Skip, OK, GotLock, ViewOnly
    }

    protected static DBObjDialogFactory instance = null;

    protected Hashtable<String, DialogInfo> searchDialogs = new Hashtable<String, DialogInfo>();
    protected Hashtable<String, DialogInfo> dialogs = new Hashtable<String, DialogInfo>();

    /**
     * Constructor - enables it to be constructed from its class name, it can only be constructed
     * one time from the default constructor otherwise it throws a RuntimeException.
     */
    public DBObjDialogFactory() {
        if (DBObjDialogFactory.instance == null) {
            DBObjDialogFactory.instance = this;

        } else {
            throw new RuntimeException("DBObjDialogFactory cannot be instanitated more than once");
        }
        init();
    }

    /**
     * Returns the instance of the DBObjDialogFactory.
     * @return the instance of the DBObjDialogFactory.
     */
    public static DBObjDialogFactory getInstance() {
        return instance;
    }

    /**
     *
     */
    protected void init() {
        try {
            Element root = AppContextMgr.getInstance().getResourceAsDOM("DialogDefs");
            if (root != null) {
                for (Iterator<?> i = root.elementIterator("dialog"); i.hasNext();) {
                    Element fileElement = (Element) i.next();
                    String type = getAttr(fileElement, "type", "display");
                    String name = getAttr(fileElement, "name", null);
                    boolean isDisplay = type.equals("display");

                    DialogInfo di = new DialogInfo(isDisplay ? null : getAttr(fileElement, "viewset", null),
                            getAttr(fileElement, "view", null), name, getAttr(fileElement, "class", null),
                            getAttr(fileElement, "idfield", null), getAttr(fileElement, "helpcontext", ""));

                    if (isDisplay) {
                        dialogs.put(name, di);
                    } else {
                        searchDialogs.put(name, di);
                    }
                }
            } else {
                String msg = "The root element for the document was null!";
                log.error(msg);
                throw new ConfigurationException(msg);
            }
        } catch (Exception ex) {
            edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
            edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(DBObjDialogFactory.class, ex);
            log.error(ex);
            ex.printStackTrace();
            throw new RuntimeException("Couldn't load DialogDefs");
        }
    }

    //----------------------------------------------------------
    // ViewBasedDialogFactoryIFace interface
    //----------------------------------------------------------

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.ViewBasedDialogFactoryIFace#createSearchDialog(java.awt.Window, java.lang.String)
     */
    public ViewBasedSearchDialogIFace createSearchDialog(final Window parent, final String name) {
        DialogInfo info = instance.searchDialogs.get(name);
        if (info != null) {
            String title = "";
            DBTableInfo ti = DBTableIdMgr.getInstance().getByClassName(info.getClassName());
            if (ti != null) {
                title = ti.getTitle() + " " + UIRegistry.getResourceString("SEARCH");
            }

            if (parent instanceof Frame) {
                return new DBObjSearchDialog((Frame) parent, info.getViewSetName(), info.getViewName(),
                        info.getSearchName(), title, info.getClassName(), info.getIdFieldName(),
                        info.getHelpContext());
            }
            // else
            return new DBObjSearchDialog((Dialog) parent, info.getViewSetName(), info.getViewName(),
                    info.getSearchName(), title, info.getClassName(), info.getIdFieldName(), info.getHelpContext());
        }
        // else
        throw new RuntimeException(
                "Couldn't create object implementing ViewBasedSearchDialogIFace by name[" + name + "]");
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.ViewBasedDialogFactoryIFace#createDisplay(java.awt.Window, java.lang.String, java.lang.String, java.lang.String, boolean, int, edu.ku.brc.ui.ViewBasedDialogFactoryIFace.FRAME_TYPE)
     */
    public ViewBasedDisplayIFace createDisplay(final Window parent, final String name, final String frameTitleArg,
            final String closeBtnTitleArg, final boolean isEditArg, final int optionsArg, final String helpContext,
            final FRAME_TYPE type) {
        boolean isEdit = isEditArg;
        int options = optionsArg;
        String closeBtnTitle = closeBtnTitleArg;

        // Override when trying to parent a Frame to a Dialog, because
        // the Frame will be placed behind the Dialog

        DialogInfo info = instance.dialogs.get(name);
        if (info != null) {
            SpecifyAppContextMgr sacm = (SpecifyAppContextMgr) AppContextMgr.getInstance();

            String viewSetName = info.getViewSetName();
            String viewName = info.getViewName();

            final ViewIFace view = sacm.getView(null, viewName);
            if (view != null) {
                viewSetName = view.getViewSetName();
            } else {
                throw new RuntimeException("Couldn't find view [" + viewName + "]");
            }

            FormLockStatus lockStatus = isLockOK("LockTitle", view,
                    MultiView.isOptionOn(options, MultiView.IS_NEW_OBJECT), isEdit);
            if (lockStatus != FormLockStatus.GotLock) {
                if (lockStatus == FormLockStatus.ViewOnly) {
                    isEdit = false;
                    options &= ~MultiView.IS_EDITTING; // Clear Bit first
                    options |= MultiView.HIDE_SAVE_BTN;
                    closeBtnTitle = UIRegistry.getResourceString("CLOSE");

                } else if (lockStatus == FormLockStatus.Skip) {
                    return null;
                }
            }

            String frameTitle = frameTitleArg;
            if (StringUtils.isEmpty(frameTitle)) {
                DBTableInfo ti = DBTableIdMgr.getInstance().getByClassName(view.getClassName());
                if (ti != null) {
                    frameTitle = ti.getTitle();
                }
            }

            ViewBasedDisplayIFace viewDisplay;
            if (type == ViewBasedDialogFactoryIFace.FRAME_TYPE.FRAME) {

                if (parent instanceof Frame) {
                    viewDisplay = new ViewBasedDisplayFrame(viewSetName, info.getViewName(), info.getSearchName(),
                            frameTitle, closeBtnTitle, info.getClassName(), info.getIdFieldName(), isEdit, options);
                } else {

                    viewDisplay = new ViewBasedDisplayDialog((Dialog) parent, viewSetName, info.getViewName(),
                            info.getSearchName(), frameTitle, closeBtnTitle, info.getClassName(),
                            info.getIdFieldName(), isEdit, options);
                }

            } else if (parent instanceof Frame) {
                viewDisplay = new ViewBasedDisplayDialog((Frame) parent, viewSetName, info.getViewName(),
                        info.getSearchName(), frameTitle, closeBtnTitle, info.getClassName(), info.getIdFieldName(),
                        isEdit, options);
            } else {
                viewDisplay = new ViewBasedDisplayDialog((Dialog) parent, viewSetName, info.getViewName(),
                        info.getSearchName(), frameTitle, closeBtnTitle, info.getClassName(), info.getIdFieldName(),
                        isEdit, options);
            }

            if (viewDisplay != null) {
                viewDisplay.setHelpContext(helpContext != null ? helpContext : info.getHelpContext());

                if (lockStatus == FormLockStatus.GotLock) {
                    final String ERR_UNLOCKING_FORM = "DBObjDialogFactory.ERR_UNLOCKING_FORM";
                    viewDisplay.setCloseListener(new ViewBasedDisplayActionAdapter() {
                        @Override
                        public boolean cancelPressed(ViewBasedDisplayIFace vbd) {
                            if (!unLockOK("LockTitle", view)) {
                                UIRegistry.showLocalizedError(ERR_UNLOCKING_FORM);
                            }
                            return true;
                        }

                        @Override
                        public boolean okPressed(ViewBasedDisplayIFace vbd) {
                            if (!unLockOK("LockTitle", view)) {
                                UIRegistry.showLocalizedError(ERR_UNLOCKING_FORM);
                            }
                            return true;
                        }
                    });
                }
            }
            return viewDisplay;
        }
        // else
        throw new RuntimeException("Couldn't create ViewBasedDisplayFrame by name[" + name
                + "] (Check the List of dialog in dailog_defs.xml)");
    }

    /**
     * Checks the tree to see if it is locked so a form for the tree can be opened. Note: this method
     * will display a localized error before it returns.
     * 
     * @param lockTitle Title (not important)
     * @param view the view that needs to be opened
     * @param isNewForm whether the form is for a new object
     * @param isEdit whether the form is to edit an object
     * @return FormLockStatus for what happened
     */
    public static FormLockStatus isLockOK(final String lockTitle, final ViewIFace view, final boolean isNewForm,
            final boolean isEdit) {
        Class<?> treeDefClass = ((SpecifyAppContextMgr) AppContextMgr.getInstance()).getTreeDefClass(view);
        if (treeDefClass != null) {
            String treeSemaphoreName = treeDefClass.getSimpleName();
            String treeFormSemaphoreName = treeDefClass.getSimpleName() + "Form";

            DBTableInfo tableInfo = DBTableIdMgr.getInstance().getByClassName(view.getClassName());
            String title = tableInfo.getTitle() + " " + "Tree";

            // If this user owns the Tree Form Lock then they can open the View
            if (TaskSemaphoreMgr.doesOwnSemaphore(treeFormSemaphoreName, TaskSemaphoreMgr.SCOPE.Discipline)) {
                return FormLockStatus.OK;
            }

            TaskSemaphoreMgr.USER_ACTION action = TaskSemaphoreMgr.USER_ACTION.OK;
            if (isEdit || isNewForm) {
                // Check to see if the Tree Lock is locked
                //if (TaskSemaphoreMgr.isLocked(lockTitle, treeSemaphoreName, TaskSemaphoreMgr.SCOPE.Discipline))

                if (BaseTreeBusRules.ALLOW_CONCURRENT_FORM_ACCESS) {
                    SpTaskSemaphore semaphore = TaskSemaphoreMgr.getLockInfo(title, treeSemaphoreName,
                            SCOPE.Discipline);
                    if (semaphore != null && semaphore.getIsLocked()) {
                        String prevLockedBy = null;
                        SpecifyUser user = AppContextMgr.getInstance().getClassObject(SpecifyUser.class);
                        if (semaphore.getOwner() != null && !semaphore.getOwner().getId().equals(user.getId())
                                && semaphore.getOwner().getAgents() != null
                                && semaphore.getOwner().getAgents().size() > 0) {
                            prevLockedBy = semaphore.getOwner().getAgents().iterator().next().getIdentityTitle();
                        }
                        if (prevLockedBy != null) {
                            UIRegistry.displayInfoMsgDlgLocalized("DBObjDialogFactory.LockedOut1", title,
                                    prevLockedBy);
                        } else {
                            UIRegistry.displayInfoMsgDlgLocalized("DBObjDialogFactory.LockedOut2", title,
                                    prevLockedBy);
                        }
                        return FormLockStatus.Skip;
                    }
                } else {
                    action = TaskSemaphoreMgr.lock(title, treeSemaphoreName, "def",
                            TaskSemaphoreMgr.SCOPE.Discipline, !isNewForm && isEdit);
                }

                if (action != TaskSemaphoreMgr.USER_ACTION.OK) {
                    if (action == TaskSemaphoreMgr.USER_ACTION.Cancel) {
                        return FormLockStatus.Skip;
                    }
                    if (isNewForm) {
                        //UIRegistry.showLocalizedError("TREE_LOCKED_NEW_OBJ");
                        return FormLockStatus.Skip;
                    }

                    if (isEdit) {
                        //UIRegistry.showLocalizedError("TREE_LOCKED_EDT_OBJ");
                        return FormLockStatus.ViewOnly;
                    }

                    return FormLockStatus.Skip;
                }
            } else {
                return FormLockStatus.ViewOnly;
            }

            // First try to grab the tree Lock
            //action = TaskSemaphoreMgr.lock(lockTitle, treeSemaphoreName, "def", TaskSemaphoreMgr.SCOPE.Discipline, false); 
            if (action == TaskSemaphoreMgr.USER_ACTION.OK) {
                // Now grab the Tree Form Lock
                if (BaseTreeBusRules.ALLOW_CONCURRENT_FORM_ACCESS) {
                    if (!TaskSemaphoreMgr.incrementUsageCount(title, treeSemaphoreName, SCOPE.Discipline)) {
                        action = USER_ACTION.Error;
                    }
                } else {
                    action = TaskSemaphoreMgr.lock(title, treeFormSemaphoreName, "def",
                            TaskSemaphoreMgr.SCOPE.Discipline, false);
                }
                if (action != TaskSemaphoreMgr.USER_ACTION.OK) {
                    if (!BaseTreeBusRules.ALLOW_CONCURRENT_FORM_ACCESS) {
                        // Since for some bizarre reason we didn't get the treeForm Lock release the tree lock.
                        TaskSemaphoreMgr.unlock(title, treeSemaphoreName, TaskSemaphoreMgr.SCOPE.Discipline);
                    }
                    UIRegistry.showLocalizedError("TREE_LOCKED_ERR_FRM");
                    return FormLockStatus.Skip;
                }
                return FormLockStatus.GotLock;

            } else {
                UIRegistry.showLocalizedError("TREE_LOCKED_ERR");
                return FormLockStatus.Skip;
            }
        }
        return FormLockStatus.OK;
    }

    /**
     * @param lockTitle
     * @param view
     * @return
     */
    public static boolean unLockOK(final String lockTitle, final ViewIFace view) {
        Class<?> treeDefClass = ((SpecifyAppContextMgr) AppContextMgr.getInstance()).getTreeDefClass(view);
        if (treeDefClass != null) {
            String treeSemaphoreName = treeDefClass.getSimpleName();
            String treeFormSemaphoreName = treeDefClass.getSimpleName() + "Form";

            DBTableInfo tableInfo = DBTableIdMgr.getInstance().getByClassName(view.getClassName());
            String title = tableInfo.getTitle() + " " + "Tree";

            if (BaseTreeBusRules.ALLOW_CONCURRENT_FORM_ACCESS) {
                return TaskSemaphoreMgr.decrementUsageCount(title, treeSemaphoreName, SCOPE.Discipline);
            }

            // If this user owns the Tree Form Lock then they can open the View
            if (!TaskSemaphoreMgr.doesOwnSemaphore(treeFormSemaphoreName, TaskSemaphoreMgr.SCOPE.Discipline)) {
                return false;
            }

            if (TaskSemaphoreMgr.unlock(title, treeFormSemaphoreName, TaskSemaphoreMgr.SCOPE.Discipline)) {
                if (TaskSemaphoreMgr.unlock(title, treeSemaphoreName, TaskSemaphoreMgr.SCOPE.Discipline)) {
                    return true;
                }
                return false;
            }
            return false;
        }
        return true;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.af.ui.ViewBasedDialogFactoryIFace#getSearchName(java.lang.String)
     */
    @Override
    public String getSearchName(String searchDlgName) {
        DialogInfo info = instance.searchDialogs.get(searchDlgName);
        return info != null ? info.getSearchName() : null;
    }

    //-----------------------------------------------------
    //-- Inner Classes
    //-----------------------------------------------------
    class DialogInfo {
        protected String viewSetName;
        protected String viewName;
        protected String searchName;
        protected String className;
        protected String idFieldName;
        protected String helpContext;

        public DialogInfo(String viewSetName, String viewName, String dialogName, String className,
                String idFieldName, String helpContext) {
            super();
            this.viewSetName = viewSetName;
            this.viewName = viewName;
            this.searchName = dialogName;
            this.className = className;
            this.idFieldName = idFieldName;
            this.helpContext = helpContext;
        }

        public String getClassName() {
            return className;
        }

        public String getViewName() {
            return viewName;
        }

        public String getIdFieldName() {
            return idFieldName;
        }

        public String getSearchName() {
            return searchName;
        }

        public String getViewSetName() {
            return viewSetName;
        }

        public String getHelpContext() {
            return helpContext;
        }
    }

}