edu.ku.brc.specify.datamodel.busrules.DeterminationBusRules.java Source code

Java tutorial

Introduction

Here is the source code for edu.ku.brc.specify.datamodel.busrules.DeterminationBusRules.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.datamodel.busrules;

import java.awt.Component;
import java.awt.Frame;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Set;

import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

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

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import edu.ku.brc.af.prefs.AppPreferences;
import edu.ku.brc.af.ui.db.PickListDBAdapterIFace;
import edu.ku.brc.af.ui.db.PickListItemIFace;
import edu.ku.brc.af.ui.forms.BaseBusRules;
import edu.ku.brc.af.ui.forms.MultiView;
import edu.ku.brc.af.ui.forms.Viewable;
import edu.ku.brc.af.ui.forms.persist.AltViewIFace.CreationMode;
import edu.ku.brc.af.ui.forms.validation.ValCheckBox;
import edu.ku.brc.af.ui.forms.validation.ValComboBox;
import edu.ku.brc.af.ui.forms.validation.ValComboBoxFromQuery;
import edu.ku.brc.dbsupport.DataProviderSessionIFace;
import edu.ku.brc.specify.datamodel.CollectionObject;
import edu.ku.brc.specify.datamodel.Determination;
import edu.ku.brc.specify.datamodel.Taxon;
import edu.ku.brc.ui.CustomDialog;
import edu.ku.brc.ui.GetSetValueIFace;
import edu.ku.brc.ui.UIHelper;
import edu.ku.brc.ui.UIRegistry;

/**
 * @author rodss
 *
 * @code_status Alpha
 *
 * Created Date: Nov 29, 2007
 *
 */
/**
 * @author rod
 *
 * @code_status Alpha
 *
 * Apr 1, 2008
 *
 */
public class DeterminationBusRules extends BaseBusRules {
    private static final Logger log = Logger.getLogger(DeterminationBusRules.class);
    private static final String DT_ALREADY_DETERMINATION = "DT_ALREADY_DETERMINATION";

    protected Determination determination = null;

    protected KeyListener nameChangeKL = null;
    protected boolean ignoreSelection = false;
    protected boolean checkedBlankUsageItem = false;
    protected boolean isNewObject = false;
    protected boolean isBlockingChange = false;

    protected ChangeListener chkbxCL = null;
    protected ValCheckBox isCurrentCheckbox = null;

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.forms.BaseBusRules#beforeFormFill()
     */
    @Override
    public void beforeFormFill() {
        determination = null;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.forms.BaseBusRules#afterFillForm(java.lang.Object)
     */
    @Override
    public void afterFillForm(final Object dataObj) {
        isBlockingChange = false;
        determination = null;

        if (formViewObj != null && formViewObj.getDataObj() instanceof Determination) {
            determination = (Determination) formViewObj.getDataObj();

            // if determination exists and is new (no key) then set current true if CO has no other dets
            Component currentComp = formViewObj.getControlByName("isCurrent");
            if (determination != null && currentComp != null) {
                if (isNewObject) {
                    // It should never be null, but, currently, it does happen.
                    // Also, now with Batch ReIdentify is will always be NULL
                    if (determination.getCollectionObject() != null) {
                        if (currentComp instanceof ValCheckBox) {
                            if (formViewObj.isCreatingNewObject()) {
                                // Do this instead of setSelected because
                                // this activates the DataChangeListener
                                isBlockingChange = true;
                                ((ValCheckBox) currentComp).doClick();
                                isBlockingChange = false;

                                // Well, if it is already checked then we just checked it to the 'off' state,
                                // so we need to re-check it so it is in the "checked state"
                                // Note: As stated in the comment above the 'doClick' the easiest way to activate
                                // all the change listeners is by simulating a mouse click.
                                // Also keep in mind that the change listener is listening for ActionEvents for the
                                // checkbox instead of ChangeEvents (ChangeEvents cause to many problems).
                                if (!((ValCheckBox) currentComp).isSelected()) {
                                    ((ValCheckBox) currentComp).doClick();
                                }

                                Set<Determination> detSet = determination.getCollectionObject().getDeterminations();
                                for (Determination d : detSet) {
                                    if (d != determination) {
                                        d.setIsCurrent(false);
                                    }
                                }
                            }

                        } else {
                            log.error("IsCurrent not set to true because form control is of unexpected type: "
                                    + currentComp.getClass().getName());
                        }
                    }
                } else {
                    ((ValCheckBox) currentComp).setValue(determination.getIsCurrent(), null);
                }
            }

            Component activeTax = formViewObj.getControlByName("preferredTaxon");
            if (activeTax != null) {
                JTextField activeTaxTF = (JTextField) activeTax;
                activeTaxTF.setFocusable(false);
                if (determination != null && determination.getPreferredTaxon() != null) {
                    activeTaxTF.setText(determination.getPreferredTaxon().getFullName());
                } else {
                    activeTaxTF.setText("");
                }
            }

            if (formViewObj.getAltView().getMode() != CreationMode.EDIT) {
                // when we're not in edit mode, we don't need to setup any listeners since the user can't change anything
                //log.debug("form is not in edit mode: no special listeners will be attached");
                return;
            }

            Component nameUsageComp = formViewObj.getControlByName("nameUsage");
            if (nameUsageComp instanceof ValComboBox) {
                // XXX this is probably not necessary anymore...
                if (!checkedBlankUsageItem) {
                    boolean fnd = false;

                    if (nameUsageComp instanceof ValComboBox) {
                        ValComboBox cbx = (ValComboBox) nameUsageComp;
                        if (cbx.getComboBox().getModel() instanceof PickListDBAdapterIFace) {
                            PickListDBAdapterIFace items = (PickListDBAdapterIFace) cbx.getComboBox().getModel();
                            for (PickListItemIFace item : items.getPickList().getItems()) {
                                if (StringUtils.isBlank(item.getValue())) {
                                    fnd = true;
                                    break;
                                }
                            }
                            if (!fnd) {
                                boolean readOnly = items.getPickList().getReadOnly();
                                if (readOnly) {
                                    items.getPickList().setReadOnly(false);
                                }
                                items.addItem("", null);
                                if (readOnly) {
                                    items.getPickList().setReadOnly(true);
                                }
                            }
                        }
                    }
                    checkedBlankUsageItem = true;
                }
                nameUsageComp.setEnabled(true);
            }

            final Component altNameComp = formViewObj.getControlByName("alternateName");
            if (altNameComp != null && determination != null) {
                altNameComp.setEnabled(determination.getTaxon() == null);
            }

            if (currentComp != null && chkbxCL == null) {
                chkbxCL = new ChangeListener() {
                    @Override
                    public void stateChanged(ChangeEvent e) {
                        adjustIsCurrentCheckbox();
                    }
                };

                isCurrentCheckbox = (ValCheckBox) currentComp;
                isCurrentCheckbox.addChangeListener(chkbxCL);
            }
        }
        isNewObject = false;
    }

    /**
     * 
     */
    private void adjustIsCurrentCheckbox() {
        if (!isBlockingChange && formViewObj != null && isCurrentCheckbox != null) {
            determination = (Determination) formViewObj.getDataObj();
            if (determination != null && isCurrentCheckbox.isSelected()) {
                //log.debug("Current: "+determination.getId());
                if (determination.getCollectionObject() != null) //co can be null for batch-re-identify
                {
                    for (Determination d : determination.getCollectionObject().getDeterminations()) {
                        if (d != determination) {
                            d.setIsCurrent(false);
                        }
                    }
                }
            }
        }
    }

    /**
     * @param kl
     * @param comp
     * 
     * Adds KeyListener to comp if it is not already a listener.
     * (This method is overkill given the current way listeners are set up.)
     */
    protected void addListenerIfNecessary(final KeyListener kl, final Component comp) {
        boolean fnd = false;
        for (KeyListener existingKl : comp.getKeyListeners()) {
            if (existingKl == kl) {
                fnd = true;
                break;
            }
        }
        if (!fnd) {
            comp.addKeyListener(kl);
        }
    }

    /**
     * @param e
     * @param taxComp
     * @param altNameComp
     * 
     * Disables the taxon field when the alternateName field is non-empty.
     * Enables the taxon field when the alternateNameField is empty.
     */
    protected void nameChanged(KeyEvent e, final ValComboBoxFromQuery taxComp, final Component altNameComp) {
        if (e.getSource() != null) {
            if (e.getSource().equals(altNameComp)) {
                taxComp.setEnabled(StringUtils.isBlank(((JTextField) altNameComp).getText()));
            } else if (e.getSource().equals(taxComp)) {
                taxonChanged(taxComp, altNameComp);
            }
        }
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.af.ui.forms.BaseBusRules#afterCreateNewObj(java.lang.Object)
     */
    @Override
    public void afterCreateNewObj(Object newDataObj) {
        isNewObject = true;
        /*Determination    deter  = (Determination)newDataObj;
        CollectionObject colObj = deter.getCollectionObject();
        if (colObj != null && deter.isCurrentDet())
        {
        for (Determination det : colObj.getDeterminations())
        {
            if (det != deter && det.isCurrentDet())
            {
                det.setIsCurrent(false);
            }
        }
        }*/
    }

    /**
     * Checks to make sure there is a single 'current' determination.
     * @param colObj the Collection Object
     * @param deter the determination for the CO
     * @return false if there is more than one determination set to current
     */
    protected boolean checkDeterminationStatus(final CollectionObject colObjArg, final Determination deter) {

        //Kind of a workaround to fix bug#9327.
        //The form system is returning the wrong colobj. 
        //Using the determination's colobj record, which, I think, will always have a value, solves the immediate problem.
        CollectionObject colObj = deter.getCollectionObject();
        if (colObj == null) {
            colObj = colObjArg;
        }

        if (deter.isCurrentDet()) {
            for (Determination det : colObj.getDeterminations()) {
                boolean isSameDet;
                if (det.getId() != null && deter.getId() != null) {
                    isSameDet = det.getId().equals(deter.getId());
                } else {
                    isSameDet = det == deter;
                }

                if (!isSameDet && det.isCurrentDet()) {
                    return false;
                }
            }
        }
        return true;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.forms.BaseBusRules#processBusinessRules(java.lang.Object, java.lang.Object, boolean)
     */
    @Override
    public STATUS processBusinessRules(final Object parentDataObj, final Object dataObj,
            final boolean isExistingObject) {
        STATUS status = super.processBusinessRules(parentDataObj, dataObj, isExistingObject);

        if (status == STATUS.OK) {
            if (!checkDeterminationStatus((CollectionObject) parentDataObj, (Determination) dataObj)) {
                reasonList.add(UIRegistry.getResourceString(DT_ALREADY_DETERMINATION));
                status = STATUS.Error;
            }
        }
        return status;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.af.ui.forms.BaseBusRules#processBusinessRules(java.lang.Object)
     */
    @Override
    public STATUS processBusinessRules(final Object dataObj) {
        STATUS status = super.processBusinessRules(dataObj);
        if (status == STATUS.OK) {
            if (formViewObj != null && formViewObj.getMVParent() != null) {
                MultiView mv = formViewObj.getMVParent();
                if (!mv.isTopLevel()) {
                    Object parentDataObj = mv.getMultiViewParent().getData();
                    if (!checkDeterminationStatus((CollectionObject) parentDataObj, (Determination) dataObj)) {
                        reasonList.add(UIRegistry.getResourceString(DT_ALREADY_DETERMINATION));
                        status = STATUS.Error;
                    }
                }
            }
        }
        return status;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.specify.datamodel.busrules.BaseBusRules#afterDeleteCommit(java.lang.Object)
     */
    @Override
    public void afterDeleteCommit(Object dataObj) {
        determination = null;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.specify.datamodel.busrules.BaseBusRules#afterSaveCommit(java.lang.Object)
     */
    @Override
    public boolean afterSaveCommit(final Object dataObj, final DataProviderSessionIFace session) {
        determination = null;
        return super.afterSaveCommit(dataObj, session);
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.specify.datamodel.busrules.BaseBusRules#formShutdown()
     */
    @Override
    public void formShutdown() {
        super.formShutdown();

        determination = null;
        chkbxCL = null;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.af.ui.forms.BaseBusRules#beforeSaveCommit(java.lang.Object, edu.ku.brc.dbsupport.DataProviderSessionIFace)
     */
    @Override
    public boolean beforeSaveCommit(Object dataObj, DataProviderSessionIFace session) throws Exception {
        if (!super.beforeSaveCommit(dataObj, session)) {
            return false;
        }

        return true;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.af.ui.forms.BaseBusRules#initialize(edu.ku.brc.af.ui.forms.Viewable)
     */
    @Override
    public void initialize(Viewable viewableArg) {
        super.initialize(viewableArg);

        if (formViewObj != null) {
            GetSetValueIFace taxonField = (GetSetValueIFace) formViewObj.getControlByName("taxon");
            if (taxonField instanceof ValComboBoxFromQuery) {
                final ValComboBoxFromQuery parentCBX = (ValComboBoxFromQuery) taxonField;
                final Component altNameComp = formViewObj.getControlByName("alternateName");

                if (nameChangeKL == null) {
                    nameChangeKL = new KeyAdapter() {
                        @Override
                        public void keyTyped(final KeyEvent e) {
                            SwingUtilities.invokeLater(new Runnable() {
                                // @Override
                                public void run() {
                                    nameChanged(e, parentCBX, altNameComp);
                                }
                            });
                        }
                    };
                }

                if (parentCBX != null) {
                    parentCBX.addListSelectionListener(new ListSelectionListener() {
                        public void valueChanged(ListSelectionEvent e) {
                            if (e == null || !e.getValueIsAdjusting()) {
                                taxonChanged(parentCBX, altNameComp);
                            }
                        }
                    });
                    addListenerIfNecessary(nameChangeKL, parentCBX);
                }

                if (altNameComp != null) {
                    addListenerIfNecessary(nameChangeKL, altNameComp);
                }
            }
        }
    }

    /**
     * @param taxonComboBox 
     * 
     * Sets text for preferredTaxon control to the selected taxon or it's accepted parent.
     * 
     * If the selected taxon is not accepted, then a dialog pops up to confirm the choice
     * with an option to use the accepted parent instead.
     * 
     * Disables/Enables AlternateName field based on whether taxon is non-null/null.
     */
    protected void taxonChanged(final ValComboBoxFromQuery taxonComboBox, final Component altTaxName) {
        Object objInForm = formViewObj.getDataObj();
        if (objInForm == null) {
            return;
        }

        Taxon formNode = ((Determination) objInForm).getTaxon();

        Taxon taxon = null;
        if (taxonComboBox.getValue() instanceof String) {
            // the data is still in the VIEW mode for some reason
            taxonComboBox.getValue();
            taxon = formNode.getParent();
        } else {
            taxon = (Taxon) taxonComboBox.getValue();
        }

        String activeTaxName = null;

        // set the tree def for the object being edited by using the parent node's tree def
        if (taxon != null) {
            if (!taxon.getIsAccepted()
                    && AppPreferences.getRemote().getBoolean("Determination.PromptToReplaceSynonym", false)) {
                PanelBuilder pb = new PanelBuilder(
                        new FormLayout("5dlu, f:p:g, 5dlu", "7dlu, c:p, 5dlu, c:p, 10dlu"));
                String msg1 = String.format(UIRegistry.getResourceString("DeterminationBusRule.SynChoiceMsg1"),
                        taxon.getFullName(), taxon.getAcceptedParent().getFullName());
                String msg2 = String.format(UIRegistry.getResourceString("DeterminationBusRule.SynChoiceMsg2"),
                        taxon.getFullName(), taxon.getAcceptedParent().getFullName());
                CellConstraints cc = new CellConstraints();
                pb.add(UIHelper.createLabel(msg1), cc.xy(2, 2));
                pb.add(UIHelper.createLabel(msg2), cc.xy(2, 4));
                String formTitle = UIRegistry.getResourceString("DeterminationBusRules.SYNONYM_INFORMATION");
                CustomDialog cd = new CustomDialog((Frame) UIRegistry.getTopWindow(), formTitle, true,
                        CustomDialog.OKCANCELHELP, pb.getPanel());
                cd.setModal(true);
                cd.setOkLabel(UIRegistry.getResourceString("DeterminationBusRules.Change"));
                cd.setCancelLabel(UIRegistry.getResourceString("DeterminationBusRules.Keep"));
                UIHelper.centerAndShow(cd);
                if (cd.getBtnPressed() == CustomDialog.OK_BTN) {
                    taxon = taxon.getAcceptedParent();
                    taxonComboBox.setValue(taxon, taxon.getFullName());
                }
            }
            if (taxon.getIsAccepted()) {
                activeTaxName = taxon.getFullName();
            } else {
                activeTaxName = taxon.getAcceptedParent().getFullName();
            }
        }

        Component activeTax = formViewObj.getControlByName("preferredTaxon");
        if (activeTax != null) {
            ((JTextField) activeTax).setText(activeTaxName);
        }

        if (altTaxName != null) {
            altTaxName.setEnabled(taxon == null);
        }
    }

}