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

Java tutorial

Introduction

Here is the source code for edu.ku.brc.specify.datamodel.busrules.CollectionObjectBusRules.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 static edu.ku.brc.ui.UIHelper.createLabel;
import static edu.ku.brc.ui.UIRegistry.getLocalizedMessage;
import static edu.ku.brc.ui.UIRegistry.getResourceString;
import static edu.ku.brc.ui.UIRegistry.showLocalizedMsg;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.Timestamp;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.border.BevelBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.SoftBevelBorder;

import org.apache.commons.lang.StringUtils;

import edu.ku.brc.af.core.AppContextMgr;
import edu.ku.brc.af.core.UsageTracker;
import edu.ku.brc.af.core.db.DBFieldInfo;
import edu.ku.brc.af.core.db.DBTableIdMgr;
import edu.ku.brc.af.core.db.DBTableInfo;
import edu.ku.brc.af.core.expresssearch.QueryAdjusterForDomain;
import edu.ku.brc.af.prefs.AppPreferences;
import edu.ku.brc.af.ui.forms.BusinessRulesIFace;
import edu.ku.brc.af.ui.forms.BusinessRulesOkDeleteIFace;
import edu.ku.brc.af.ui.forms.FormDataObjIFace;
import edu.ku.brc.af.ui.forms.FormViewObj;
import edu.ku.brc.af.ui.forms.FormViewObj.FVOFieldInfo;
import edu.ku.brc.af.ui.forms.MultiView;
import edu.ku.brc.af.ui.forms.Viewable;
import edu.ku.brc.af.ui.forms.formatters.UIFieldFormatterIFace;
import edu.ku.brc.af.ui.forms.persist.AltViewIFace;
import edu.ku.brc.af.ui.forms.persist.FormCellFieldIFace;
import edu.ku.brc.af.ui.forms.persist.FormViewDef;
import edu.ku.brc.af.ui.forms.persist.ViewIFace;
import edu.ku.brc.dbsupport.DataProviderFactory;
import edu.ku.brc.dbsupport.DataProviderSessionIFace;
import edu.ku.brc.specify.config.DisciplineType;
import edu.ku.brc.specify.conversion.BasicSQLUtils;
import edu.ku.brc.specify.datamodel.Accession;
import edu.ku.brc.specify.datamodel.Agent;
import edu.ku.brc.specify.datamodel.CollectingEvent;
import edu.ku.brc.specify.datamodel.Collection;
import edu.ku.brc.specify.datamodel.CollectionObject;
import edu.ku.brc.specify.datamodel.CollectionObjectAttribute;
import edu.ku.brc.specify.datamodel.Container;
import edu.ku.brc.specify.datamodel.DeaccessionPreparation;
import edu.ku.brc.specify.datamodel.Determination;
import edu.ku.brc.specify.datamodel.Discipline;
import edu.ku.brc.specify.datamodel.LoanPreparation;
import edu.ku.brc.specify.datamodel.PaleoContext;
import edu.ku.brc.specify.datamodel.PrepType;
import edu.ku.brc.specify.datamodel.Preparation;
import edu.ku.brc.specify.datamodel.Project;
import edu.ku.brc.specify.datamodel.RecordSet;
import edu.ku.brc.specify.datamodel.SpecifyUser;
import edu.ku.brc.specify.plugins.SeriesProcCatNumPlugin;
import edu.ku.brc.specify.tasks.RecordSetTask;
import edu.ku.brc.specify.tasks.subpane.wb.wbuploader.Uploader;
import edu.ku.brc.ui.CommandAction;
import edu.ku.brc.ui.CommandDispatcher;
import edu.ku.brc.ui.CustomDialog;
import edu.ku.brc.ui.UIHelper;
import edu.ku.brc.ui.UIRegistry;
import edu.ku.brc.ui.dnd.SimpleGlassPane;
import edu.ku.brc.util.Pair;

/**
 * @author rods
 *
 * @code_status Beta
 *
 * Created Date: Jan 24, 2007
 *
 */
public class CollectionObjectBusRules extends AttachmentOwnerBaseBusRules {
    private static final String CATNUMNAME = "catalogNumber";

    public static final int MAXSERIESSIZE = 500;

    private static final String GLASSKEY = "DOBATCHCREATE";
    private static final String NonIncrementingCatNum = "NonIncrementingCatNum";
    private static final String BatchSaveSuccess = "CollectionObjectBusRules.BatchSaveSuccess";
    private static final String BatchSaveErrors = "CollectionObjectBusRules.BatchSaveErrors";
    private static final String BatchSaveErrorsTitle = "CollectionObjectBusRules.BatchSaveErrorsTitle";
    private static final String BatchRSBaseName = "CollectionObjectBusRules.BatchRSBaseName";
    private static final String InvalidEntryMsg = "CollectionObjectBusRules.InvalidEntryMsg";
    private static final String InvalidEntryTitle = "CollectionObjectBusRules.InvalidEntryTitle";
    private static final String InvalidBatchEntry = "CollectionObjectBusRules.InvalidBatchEntry";
    private static final String CatNumInUse = "CollectionObjectBusRules.CatNumInUse";
    private static final String IncompleteSaveFlag = "CollectionObjectBusRules.IncompleteSaveFlag";
    private static final String InvalidBatchItems = "CollectionObjectBusRules.InvalidBatchItems";

    //private static final Logger  log = Logger.getLogger(CollectionObjectBusRules.class);

    private CollectingEvent cachedColEve = null;
    private PaleoContext cachedPalCon = null;
    private JButton generateLabelBtn = null;
    private JCheckBox generateLabelChk = null;
    private Component paleoContextCmp = null;
    private AtomicBoolean processingSeries = new AtomicBoolean(false);

    private Integer defaultPrepTypeId = null;
    private String defValForPrepType = null;

    protected boolean checkFieldNumberDupl = false;
    protected boolean checkCatNumberEmpty = false;

    /**
     * Constructor.
     */
    public CollectionObjectBusRules() {
        super(CollectionObject.class);
    }

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

        if (formViewObj != null && formViewObj.isEditing()) {
            checkFieldNumberDupl = AppPreferences.getRemote().getBoolean("CO_CHK_FIELDNUM_DUPS", false);
            checkCatNumberEmpty = AppPreferences.getRemote().getBoolean("CO_CHK_CATNUM_NOEMPTY", false);

            Component comp = formViewObj.getControlByName("generateLabelBtn");
            if (comp instanceof JButton) {
                generateLabelBtn = (JButton) comp;
                //generateLabelBtn.setVisible(false);
                generateLabelBtn.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                CommandAction cmdAction = new CommandAction("Data_Entry", "PrintColObjLabel",
                                        formViewObj.getDataObj());
                                CommandDispatcher.dispatch(cmdAction);
                            }
                        });
                    }
                });
            }

            comp = formViewObj.getControlByName("generateLabelChk");
            if (comp instanceof JCheckBox) {
                generateLabelChk = (JCheckBox) comp;
                //generateLabelChk.setVisible(false);
            }
        }
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.af.ui.forms.BaseBusRules#afterFillForm(java.lang.Object)
     */
    @Override
    public void afterFillForm(Object dataObj) {
        super.afterFillForm(dataObj);

        if (formViewObj != null) {
            if (formViewObj.getDataObj() instanceof CollectionObject) {
                CollectionObject colObj = (CollectionObject) dataObj;

                MultiView mvParent = formViewObj.getMVParent();
                boolean isNewObj = colObj.getId() == null;
                boolean isEdit = mvParent.isEditable();

                if (generateLabelChk != null) {
                    generateLabelChk.setVisible(isEdit);
                }

                if (generateLabelBtn != null) {
                    generateLabelBtn.setVisible(isEdit);
                    generateLabelBtn.setEnabled(!isNewObj);
                }
            }

            Pair<Component, FormViewObj> paleoContext = formViewObj.getControlWithFormViewObjByName("paleoContext");
            if (paleoContext != null && paleoContextCmp == null && paleoContext.getSecond() == this.formViewObj) {
                paleoContextCmp = paleoContext.getFirst();
                Discipline disc = (AppContextMgr.getInstance().getClassObject(Discipline.class));
                if (!"collectionobject".equalsIgnoreCase(disc.getPaleoContextChildTable())) {
                    UIRegistry.showLocalizedMsg("CollectionObjectBusRules.PaleoRelationshipDisabled");
                    paleoContextCmp.setEnabled(false);
                } else {
                    UsageTracker
                            .incrUsageCount("CollectionObjectBusRules.AfterFillForm.PaleoRelationshipDisplayed");
                }
            }
        }
    }

    /**
     * @param id
     * @return
     */
    public static PrepType getPrepTypeFromId(final Integer id) {
        DataProviderSessionIFace session = null;
        try {
            session = DataProviderFactory.getInstance().createSession();
            return session.get(PrepType.class, id);

        } catch (Exception ex) {
            ex.printStackTrace();
            edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
            edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(CollectionObjectBusRules.class, ex);

        } finally {
            if (session != null)
                session.close();
        }
        return null;
    }

    /**
     * @param disciplineType
     * @return
     */
    public static Integer getPrepTypeIdFromDefVal(final String defaultValue) {
        Integer defPrepTypeId = null;
        if (StringUtils.isNotEmpty(defaultValue)) {
            String sqlStr = String.format(
                    "SELECT PrepTypeId, Name FROM preptype WHERE collectionId = COLLID AND Name = '%s'",
                    defaultValue);
            sqlStr = QueryAdjusterForDomain.getInstance().adjustSQL(sqlStr);
            defPrepTypeId = BasicSQLUtils.getNumRecords(sqlStr);
        }
        return defPrepTypeId;
    }

    /**
     * @return the default preparer
     */
    protected Agent getDefaultPreparedByAgent() {
        return Agent.getUserAgent();
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.specify.datamodel.busrules.BaseBusRules#addChildrenToNewDataObjects(java.lang.Object)
     */
    @Override
    public void addChildrenToNewDataObjects(final Object newDataObj) {
        super.addChildrenToNewDataObjects(newDataObj);

        Collection collection = AppContextMgr.getInstance().getClassObject(Collection.class);
        Boolean doCreateCE = collection.getIsEmbeddedCollectingEvent();
        CollectionObject colObj = (CollectionObject) newDataObj;
        if (doCreateCE) {
            // Carry Forward may have already added 
            // some values so we need to check to make sure
            // before adding new ones automatically.
            if (colObj.getCollectingEvent() == null) {
                CollectingEvent ce = new CollectingEvent();
                ce.initialize();
                colObj.addReference(ce, "collectingEvent");
            }
        }

        //        Boolean    doCreatePC = AppContextMgr.getInstance().getClassObject(Discipline.class).getIsPaleoContextEmbedded();
        //        //CollectionObject colObj = (CollectionObject)newDataObj;
        //        if (doCreatePC)
        //        {
        //            // Carry Forward may have already added 
        //            // some values so we need to check to make sure
        //            // before adding new ones automatically.
        //            if (colObj.getPaleoContext() == null)
        //            {
        //                PaleoContext pc = new PaleoContext();
        //                pc.initialize();
        //                colObj.addReference(pc, "paleoContext");
        //            }
        //        }

        AppPreferences remotePrefs = AppPreferences.getRemote();
        if (remotePrefs != null) {
            Integer colId = collection.getId();
            if (remotePrefs.getBoolean("CO_CREATE_COA_" + colId, false)) {
                CollectionObjectAttribute coa = new CollectionObjectAttribute();
                coa.initialize();
                colObj.addReference(coa, "collectionObjectAttribute");
            }

            CollectionObject carryFwdCO = null;
            List<FVOFieldInfo> fieldList = null;
            boolean isCarryFwdReady = false;

            if (formViewObj != null && formViewObj.getCarryFwdDataObj() != null && formViewObj.isDoCarryForward()
                    && formViewObj.getCarryFwdInfo() != null) {
                carryFwdCO = (CollectionObject) formViewObj.getCarryFwdDataObj();
                fieldList = formViewObj.getCarryFwdInfo().getFieldList();
                isCarryFwdReady = fieldList.size() > 0;
            }

            if (remotePrefs.getBoolean("CO_CREATE_PREP_" + colId, false)) {
                if (StringUtils.isEmpty(defValForPrepType)) {
                    defValForPrepType = getDefValForPrepTypeHaveOnForm();
                }

                if (defaultPrepTypeId == null && StringUtils.isNotEmpty(defValForPrepType)) {
                    defaultPrepTypeId = getPrepTypeIdFromDefVal(defValForPrepType);
                }

                if (defaultPrepTypeId != null) {
                    boolean isOKToCreate = true;
                    if (isCarryFwdReady) {
                        isOKToCreate = fieldList.contains("Preparations")
                                && carryFwdCO.getPreparations().size() == 0;
                    }

                    if (isOKToCreate) {
                        PrepType prepType = getPrepTypeFromId(defaultPrepTypeId);
                        if (prepType != null) {
                            Preparation prep = new Preparation();
                            prep.initialize();
                            prep.addReference(prepType, "prepType");
                            colObj.addReference(prep, "preparations");

                        } else {
                            UIRegistry.showError("Unable to load PrepType with id: " + defaultPrepTypeId);
                        }
                    }
                }
            }

            if (remotePrefs.getBoolean("CO_CREATE_DET_" + colId, false)) {
                boolean isOKToCreate = true;
                if (isCarryFwdReady) {
                    isOKToCreate = fieldList.contains("Determinations")
                            && carryFwdCO.getDeterminations().size() == 0;
                }

                if (isOKToCreate) {
                    Determination det = new Determination();
                    det.initialize();
                    det.setIsCurrent(true);
                    colObj.addReference(det, "determinations");
                }
            }
        }
    }

    /*
         
    if (status == STATUS.OK)
    {
        String sqlPart = String.format("SELECT COUNT(*) FROM collectionobject co INNER JOIN determination d ON co.CollectionObjectID = d.CollectionObjectID WHERE co.CollectionObjectID = %d", colObj.getId());
        // check that a current determination exists
        int detCnt = BasicSQLUtils.getCountAsInt(sqlPart);
        if (detCnt > 0)
        {
            String sql = String.format("%s AND IsCurrent <> 0", sqlPart);
            int currents = BasicSQLUtils.getCountAsInt(sql);
                
            if (currents != 1)
            {
                status = STATUS.Error;
            }
            if (currents == 0)
            {
                reasonList.add(getI10N("CURRENT_DET_REQUIRED"));
            }
            else
            {
                reasonList.add(getI10N("ONLY_ONE_CURRENT_DET"));
            }
        }
    }
         
     */

    /**
     * @param key
     * @return
     */
    private String getI10N(final String key) {
        return getResourceString("CollectionObjectBusRules." + key);
    }

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

        CollectionObject colObj = (CollectionObject) dataObj;

        if (!processingSeries.get() && getBatchPlugIn() != null) {
            if (colObj != null && colObj.getId() != null) {
                reasonList.add(getI10N("AttemptedEditOfBatch"));
                status = STATUS.Error;
            }
        }

        if (status == STATUS.OK && colObj.getId() == null) {
            DBTableInfo tblInfo = DBTableIdMgr.getInstance().getInfoById(1); // don't need to check for null
            DBFieldInfo fieldInfo = tblInfo.getFieldByName(CATNUMNAME);
            UIFieldFormatterIFace fmt = fieldInfo.getFormatter();
            if ((fmt != null && fmt.getAutoNumber() == null) || !formViewObj.isAutoNumberOn()) {
                status = processBusinessRules(null, dataObj, true);

            } else if (checkFieldNumberDupl) {
                status = checkForFieldNumDup(dataObj);
            }
        }

        if (status == STATUS.OK) {
            if (status == STATUS.OK && checkCatNumberEmpty && StringUtils.isEmpty(colObj.getCatalogNumber())) {
                reasonList.add(getI10N("NO_EMPTY_CAT_NUMS"));
                status = STATUS.Error;
            }

            // check that a current determination exists
            int cnt = ((CollectionObject) dataObj).getDeterminations().size();
            if (cnt > 0) {
                int currents = 0;
                for (Determination det : ((CollectionObject) dataObj).getDeterminations()) {
                    if (det.isCurrentDet()) {
                        currents++;
                    }
                }

                if (currents != 1) {
                    status = STATUS.Error;
                }
                if (currents == 0) {
                    reasonList.add(getI10N("CURRENT_DET_REQUIRED"));
                } else if (cnt > 1) {
                    reasonList.add(getI10N("ONLY_ONE_CURRENT_DET"));
                }
            }
        }
        return status;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.af.ui.forms.BaseBusRules#beforeFormFill()
     */
    /*    @Override
        public void beforeFormFill()
        {
    super.beforeFormFill();
        
    Collection     collection = AppContextMgr.getInstance().getClassObject(Collection.class);
    AppPreferences remotePrefs = AppPreferences.getRemote();
    if (collection != null && remotePrefs != null && viewable instanceof TableViewObj) // none of these should ever be null
    {
        Integer colId = collection.getId();
        if (remotePrefs.getBoolean("CO_CREATE_PREP_"+colId, false))
        {
            FormViewObj fvo = null;
            if (viewable instanceof TableViewObj)
            {
                ViewIFace view = AppContextMgr.getInstance().getView("Preparation");
                if (view != null && view instanceof FormViewObj)
                {
                    fvo = (FormViewObj)view;
                        
                } else
                {
                    // error
                }
            } else
            {
                fvo = formViewObj;
            }
                
            if (fvo != null)
            {
                FVOFieldInfo fldInfo = fvo.getFieldInfoForName("prepType");
                if (fldInfo != null)
                {
                    FormCellFieldIFace fcf = (FormCellFieldIFace)fldInfo.getFormCell();
                    if (StringUtils.isEmpty(fcf.getDefaultValue()) && 
                        fldInfo.getComp() instanceof ValComboBox)
                    {
                        ValComboBox cbx = (ValComboBox)fldInfo.getComp();
                        if (cbx.getComboBox().getModel().getSize() > 0)
                        {
                            cbx.getComboBox().setSelectedIndex(0);
                        }
                    }
                }
            }
        }
    }
        }
        */

    /**
     * @return FormCellFieldIFace object for the Prep Type field on the form.
     */
    public static FormCellFieldIFace getPrepTypeFieldCellField() {
        ViewIFace view = AppContextMgr.getInstance().getView("Preparation");
        if (view != null) {
            AltViewIFace altView = view.getAltView("Preparation Edit");
            if (altView != null && altView.getViewDef() instanceof FormViewDef) {
                FormViewDef fvd = (FormViewDef) altView.getViewDef();
                return (FormCellFieldIFace) fvd.getFormCellByName("prepType");
            }
        }
        return null;
    }

    /**
     * Checks to see if the PrepType Field on the PrepType Form as a Default Value
     * @return true if there is a default value for the Prep Tyep on the Prep Form
     */
    public static String getDefValForPrepTypeHaveOnForm() {
        FormCellFieldIFace fcf = getPrepTypeFieldCellField();
        if (fcf != null) {
            return fcf.getDefaultValue();
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see edu.ku.brc.ui.forms.BaseBusRules#beforeMerge(java.lang.Object,
     *      edu.ku.brc.dbsupport.DataProviderSessionIFace)
     */
    @Override
    public void beforeMerge(final Object dataObj, final DataProviderSessionIFace session) {
        CollectionObject colObj = (CollectionObject) dataObj;

        super.beforeMerge(dataObj, session);

        if (AppContextMgr.getInstance().getClassObject(Collection.class).getIsEmbeddedCollectingEvent()) {
            cachedColEve = colObj != null ? colObj.getCollectingEvent() : null;
            if (colObj != null && cachedColEve != null) {
                colObj.setCollectingEvent(null);
                try {
                    cachedColEve.getCollectionObjects().clear();
                } catch (org.hibernate.LazyInitializationException ex) {
                    //ex.printStackTrace();
                } catch (Exception ex) {
                    //ex.printStackTrace();
                }
            }
        }

        if (AppContextMgr.getInstance().getClassObject(Discipline.class).getIsPaleoContextEmbedded()) {
            cachedPalCon = colObj != null ? colObj.getPaleoContext() : null;
            if (colObj != null && cachedPalCon != null) {
                colObj.setPaleoContext(null);
                try {
                    cachedPalCon.getCollectionObjects().clear();
                } catch (org.hibernate.LazyInitializationException ex) {
                    //ex.printStackTrace();
                } catch (Exception ex) {
                    //ex.printStackTrace();
                }
            }
        }

    }

    /**
     * @param attOwner
     */
    @Override
    protected void addExtraObjectForProcessing(final Object dObjAtt) {
        super.addExtraObjectForProcessing(dObjAtt);

        CollectionObject colObj = (CollectionObject) dObjAtt;

        if (AppContextMgr.getInstance().getClassObject(Collection.class).getIsEmbeddedCollectingEvent()
                && (colObj.getCollectingEvent() != null || cachedColEve != null)) {
            super.addExtraObjectForProcessing(cachedColEve != null ? cachedColEve : colObj.getCollectingEvent());
        }

        for (Preparation prep : colObj.getPreparations()) {
            super.addExtraObjectForProcessing(prep);
        }
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.specify.datamodel.busrules.AttachmentOwnerBaseBusRules#beforeSave(java.lang.Object, edu.ku.brc.dbsupport.DataProviderSessionIFace)
     */
    @Override
    public void beforeSave(Object dataObj, DataProviderSessionIFace session) {
        CollectionObject colObj = (CollectionObject) dataObj;

        super.beforeSave(dataObj, session);

        if (AppContextMgr.getInstance().getClassObject(Collection.class).getIsEmbeddedCollectingEvent()) {
            if (cachedColEve != null) {
                try {
                    if (cachedColEve != null && cachedColEve.getId() != null) {
                        cachedColEve = session.merge(cachedColEve);
                    } else {
                        session.save(cachedColEve);
                    }

                } catch (Exception ex) {
                    ex.printStackTrace();
                    edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                    edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(CollectionObjectBusRules.class,
                            ex);
                }
            }

            // Hook back up
            if (cachedColEve != null && colObj != null) {
                colObj.setCollectingEvent(cachedColEve);
                cachedColEve.getCollectionObjects().add(colObj);
                cachedColEve = null;
            } else {
                log.warn("The CE " + cachedColEve + " was null or the CO " + colObj + " was null");
            }
        }

        if (AppContextMgr.getInstance().getClassObject(Discipline.class).getIsPaleoContextEmbedded()) {
            if (cachedPalCon != null) {
                try {
                    if (cachedPalCon != null && cachedPalCon.getId() != null) {
                        cachedPalCon = session.merge(cachedPalCon);
                    } else {
                        session.save(cachedPalCon);
                    }

                } catch (Exception ex) {
                    ex.printStackTrace();
                    edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                    edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(CollectionObjectBusRules.class,
                            ex);
                }
            }

            // Hook back up
            if (cachedPalCon != null && colObj != null) {
                colObj.setPaleoContext(cachedPalCon);
                cachedPalCon.getCollectionObjects().add(colObj);
                cachedPalCon = null;
            } else {
                log.warn("The PC " + cachedPalCon + " was null or the CO " + colObj + " was null");
            }
        }

    }

    /* (non-Javadoc)
     * @see edu.ku.brc.specify.datamodel.busrules.AttachmentOwnerBaseBusRules#beforeDeleteCommit(java.lang.Object, edu.ku.brc.dbsupport.DataProviderSessionIFace)
     */
    @Override
    public boolean beforeDeleteCommit(Object dataObj, DataProviderSessionIFace session) throws Exception {
        boolean ok = super.beforeDeleteCommit(dataObj, session);

        if (ok && dataObj instanceof CollectionObject) {
            CollectionObject colObj = (CollectionObject) dataObj;
            Collection collection = AppContextMgr.getInstance().getClassObject(Collection.class);
            if (collection != null && collection.getIsEmbeddedCollectingEvent()) {
                CollectingEvent ce = colObj.getCollectingEvent();
                if (ce != null) {
                    try {
                        session.delete(ce);
                        return true;

                    } catch (Exception ex) {
                        edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                        edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(CollectionObjectBusRules.class,
                                ex);
                        ex.printStackTrace();
                        return false;
                    }
                }
            }

            Discipline discipline = AppContextMgr.getInstance().getClassObject(Discipline.class);
            if (discipline != null && discipline.getIsPaleoContextEmbedded()) {
                PaleoContext pc = colObj.getPaleoContext();
                if (pc != null) {
                    try {
                        session.delete(pc);
                        return true;

                    } catch (Exception ex) {
                        edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                        edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(CollectionObjectBusRules.class,
                                ex);
                        ex.printStackTrace();
                        return false;
                    }
                }
            }

            if (colObj.getContainerOwner() != null) {
                Container parentContainer = colObj.getContainerOwner();
                parentContainer.getChildren().remove(colObj);
                colObj.setContainerOwner(null);

                if (formViewObj != null) {
                    formViewObj.getMVParent().getTopLevel().addToBeSavedItem(parentContainer);
                }
            }

            if (colObj.getContainer() != null) {
                Container parentContainer = colObj.getContainer();
                parentContainer.getCollectionObjectKids().remove(colObj);
                colObj.setContainer(null);

                if (formViewObj != null) {
                    formViewObj.getMVParent().getTopLevel().addToBeSavedItem(parentContainer);
                }

            }
        }
        return ok;
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.af.ui.forms.BaseBusRules#afterSaveCommit(java.lang.Object, edu.ku.brc.dbsupport.DataProviderSessionIFace)
     */
    @Override
    public boolean afterSaveCommit(final Object dataObj, final DataProviderSessionIFace session) {
        if (formViewObj != null && formViewObj.isEditing()) {
            Component comp = formViewObj.getControlByName("generateLabelChk");
            if (comp instanceof JCheckBox && ((JCheckBox) comp).isSelected()) {
                CommandAction cmdAction = new CommandAction("Data_Entry", "PrintColObjLabel",
                        formViewObj.getDataObj());
                CommandDispatcher.dispatch(cmdAction);
            }
        }

        //doSeriesProcessing();

        return super.afterSaveCommit(dataObj, session);
    }

    /* (non-Javadoc)
    * @see edu.ku.brc.af.ui.forms.BaseBusRules#saveFinalization(java.lang.Object)
    */
    @Override
    public void saveFinalization(Object dataObj) {
        super.saveFinalization(dataObj);
        doSeriesProcessing();
    }

    /**
      * @param batchBeginIsDup
      * @return
      */
    private STATUS isCheckDuplicateBatchNumbersOK(final boolean batchBeginIsDup) {
        STATUS result = STATUS.OK;
        if (!processingSeries.get()) {
            SeriesProcCatNumPlugin batchCtrl = getBatchPlugIn();
            if (batchCtrl != null) {
                result = processBatchContents(batchCtrl.getStartAndEndCatNumbers(), true, batchBeginIsDup,
                        new Vector<String>());
                if (result.equals(STATUS.Error)) {
                    if (batchBeginIsDup) {
                        reasonList.remove(reasonList.size() - 1);
                    }
                    reasonList.add(UIRegistry.getResourceString(InvalidBatchEntry));
                }
            }
        }
        return result;
    }

    /**
     * Show objects that were not added to the batch
     */
    @SuppressWarnings("rawtypes")
    protected void showBatchErrorObjects(final Vector<String> badObjects, final String TitleKey,
            final String MsgKey) {
        JPanel pane = new JPanel(new BorderLayout());
        JLabel lbl = createLabel(getResourceString(MsgKey));
        lbl.setBorder(new EmptyBorder(3, 1, 2, 0));
        pane.add(lbl, BorderLayout.NORTH);
        JPanel lstPane = new JPanel(new BorderLayout());
        JList lst = UIHelper.createList(badObjects);
        lst.setBorder(new SoftBevelBorder(BevelBorder.LOWERED));
        lstPane.setBorder(new EmptyBorder(1, 1, 10, 1));
        lstPane.add(lst, BorderLayout.CENTER);
        JScrollPane sp = new JScrollPane(lstPane);
        //pane.add(lstPane, BorderLayout.CENTER);
        pane.add(sp, BorderLayout.CENTER);
        //pane.setPreferredSize(new Dimension((int )lbl.getPreferredSize().getWidth() + 5, (int )lst.getPreferredScrollableViewportSize().getHeight() + 5));
        //pane.setPreferredSize(new Dimension((int )lbl.getPreferredSize().getWidth() + 5, (int )lst.getPreferredScrollableViewportSize().getHeight() + 5));
        CustomDialog dlg = new CustomDialog((Frame) UIRegistry.getTopWindow(),
                UIRegistry.getResourceString(TitleKey), true, CustomDialog.OKHELP, pane);
        UIHelper.centerAndShow(dlg);
        dlg.dispose();
    }

    /**
     * @param catNumPair
     * @param validate
     * @param invalidStart
     * @param nums
     * @return
     */
    private STATUS processBatchContents(Pair<String, String> catNumPair, boolean validate, boolean invalidStart,
            Vector<String> nums) {
        DBFieldInfo CatNumFld = DBTableIdMgr.getInstance().getInfoById(CollectionObject.getClassTableId())
                .getFieldByColumnName("CatalogNumber");
        final UIFieldFormatterIFace formatter = CatNumFld.getFormatter();
        if (!formatter.isIncrementer()) {
            //XXX this will have been checked earlier, right?
            //UIRegistry.showLocalizedError(NonIncrementingCatNum);
            return STATUS.Error;
        }

        Vector<String> duplicates = new Vector<String>();
        String catNum = catNumPair.getFirst();
        if (invalidStart) {
            duplicates.add(formatter.formatToUI(catNum) + " - " + getResourceString(CatNumInUse));
        }
        Integer collId = AppContextMgr.getInstance().getClassObject(Collection.class).getId();
        String coIdSql = "select CollectionObjectID from collectionobject where CollectionMemberID = " + collId
                + " and CatalogNumber = '";
        //XXX comparing catnums ...
        while (!catNum.equals(catNumPair.getSecond()) && nums.size() <= MAXSERIESSIZE) {
            catNum = formatter.getNextNumber(catNum, true);
            //catNum = (String )formatter.formatFromUI(String.valueOf(Integer.valueOf(catNum).intValue() + 1));
            if (!validate || BasicSQLUtils.querySingleObj(coIdSql + catNum + "'") == null) {
                nums.add(catNum);
            } else {
                duplicates.add(formatter.formatToUI(catNum) + " - " + getResourceString(CatNumInUse));
            }
        }

        if (nums.size() > MAXSERIESSIZE || duplicates.size() > 0) {
            if (nums.size() > MAXSERIESSIZE) {
                duplicates.clear(); //it may contain irrelevant cat nums
            }
            if (duplicates.size() == 0) {
                UIRegistry.displayErrorDlgLocalized(InvalidEntryMsg, MAXSERIESSIZE);
            } else {
                showBatchErrorObjects(duplicates, InvalidEntryTitle, InvalidBatchItems);
            }
            return STATUS.Error;
        }
        return STATUS.OK;
    }

    /**
     * @return the SeriesProcCatNumPlugin if the current entry is a batch.
     * if the current entry is not a batch then return null.
     */
    private SeriesProcCatNumPlugin getBatchPlugIn() {
        if (formViewObj != null) {
            Component catNumComp = formViewObj.getControlByName(CATNUMNAME);
            if (catNumComp instanceof SeriesProcCatNumPlugin) {
                SeriesProcCatNumPlugin spCatNumPlugin = (SeriesProcCatNumPlugin) catNumComp;
                if (spCatNumPlugin.isExpanded()) {
                    DBTableInfo tblInfo = DBTableIdMgr.getInstance()
                            .getInfoById(CollectionObject.getClassTableId()); // don't need to check for null
                    DBFieldInfo fieldInfo = tblInfo.getFieldByName(CATNUMNAME);
                    UIFieldFormatterIFace fmt = fieldInfo.getFormatter();
                    if (fmt != null && fmt.getAutoNumber() != null && !formViewObj.isAutoNumberOn()) {

                        return spCatNumPlugin;
                    }
                }
            }
        }
        return null;
    }

    /**
     * 
     */
    public void doSeriesProcessing() {
        if (!processingSeries.get()) {
            SeriesProcCatNumPlugin spCatNumPlugin = getBatchPlugIn();
            if (spCatNumPlugin != null) {
                doCreateBatchOfColObj(spCatNumPlugin.getStartAndEndCatNumbers());
            }
        }
    }

    /**
     * 
     */
    public void doCreateBatchOfColObj(final Pair<String, String> catNumPair) {
        if (catNumPair.getFirst().equals(catNumPair.getSecond())) {
            return;
        }

        DBFieldInfo CatNumFld = DBTableIdMgr.getInstance().getInfoById(CollectionObject.getClassTableId())
                .getFieldByColumnName("CatalogNumber");
        final UIFieldFormatterIFace formatter = CatNumFld.getFormatter();
        if (!formatter.isIncrementer()) {
            //XXX this will have been checked earlier, right?
            UIRegistry.showLocalizedError(NonIncrementingCatNum);
            return;
        }

        final Vector<String> nums = new Vector<String>();
        processBatchContents(catNumPair, false, false, nums);
        SwingWorker<Integer, Integer> worker = new SwingWorker<Integer, Integer>() {
            private Vector<Pair<Integer, String>> objectsAdded = new Vector<Pair<Integer, String>>();
            private Vector<String> objectsNotAdded = new Vector<String>();
            private RecordSet batchRS;
            //private boolean invalidEntry = false;

            /* (non-Javadoc)
             * @see javax.swing.SwingWorker#doInBackground()
             */
            @Override
            protected Integer doInBackground() throws Exception {

                String catNum = catNumPair.getFirst();
                Integer collId = AppContextMgr.getInstance().getClassObject(Collection.class).getId();
                String coIdSql = "select CollectionObjectID from collectionobject where CollectionMemberID = "
                        + collId + " and CatalogNumber = '";
                objectsAdded.add(new Pair<Integer, String>(
                        (Integer) BasicSQLUtils.querySingleObj(coIdSql + catNum + "'"), catNum));

                int cnt = 0;
                CollectionObject co = null;
                //CollectionObject carryForwardCo = (CollectionObject )formViewObj.getDataObj();
                CollectionObject carryForwardCo;
                DataProviderSessionIFace session = DataProviderFactory.getInstance().createSession();
                try {
                    carryForwardCo = session.get(CollectionObject.class,
                            ((CollectionObject) formViewObj.getDataObj()).getId());
                } finally {
                    session.close();
                }

                Thread.sleep(666); //Perhaps this is unnecessary, but it seems
                //to prevent sporadic "illegal access to loading collection" hibernate errors.
                try {
                    for (String currentCat : nums) {
                        try {
                            co = new CollectionObject();
                            co.initialize();

                            //Collection doesn't get set in co.initialize(), or carryForward, but it needs to be set.
                            co.setCollection(AppContextMgr.getInstance().getClassObject(Collection.class));
                            //ditto, but doesn't so much need to be set
                            co.setModifiedByAgent(carryForwardCo.getModifiedByAgent());

                            co.setCatalogNumber(currentCat);
                            formViewObj.setNewObject(co);

                            if (formViewObj.saveObject()) {
                                objectsAdded.add(new Pair<Integer, String>(
                                        (Integer) BasicSQLUtils
                                                .querySingleObj(coIdSql + co.getCatalogNumber() + "'"),
                                        co.getCatalogNumber()));
                            } else {
                                objectsNotAdded.add(formatter.formatToUI(co.getCatalogNumber()).toString());
                            }
                        } catch (Exception ex) {
                            log.error(ex);
                            objectsNotAdded.add(formatter.formatToUI(currentCat) + ": "
                                    + (ex.getLocalizedMessage() == null ? "" : ex.getLocalizedMessage()));
                        }
                        cnt++;
                        firePropertyChange(GLASSKEY, 0, cnt);
                    }
                    firePropertyChange(GLASSKEY, 0, nums.size());

                } catch (Exception ex) {
                    edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                    edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(Uploader.class, ex);
                }
                formViewObj.setDataObj(carryForwardCo);
                saveBatchObjectsToRS();
                return objectsAdded.size();
            }

            /**
             * Save the objects added to a Recordset
             */
            protected void saveBatchObjectsToRS() {
                batchRS = new RecordSet();
                batchRS.initialize();
                batchRS.setDbTableId(CollectionObject.getClassTableId());
                String name = getResourceString(BatchRSBaseName) + " " + formatter.formatToUI(catNumPair.getFirst())
                        + "-" + formatter.formatToUI(catNumPair.getSecond());
                if (objectsNotAdded.size() > 0) {
                    name += "-" + UIRegistry.getResourceString(IncompleteSaveFlag);
                }
                batchRS.setName(name);
                for (Pair<Integer, String> obj : objectsAdded) {
                    batchRS.addItem(obj.getFirst());
                }
                DataProviderSessionIFace session = DataProviderFactory.getInstance().createSession();
                boolean transOpen = false;
                try {
                    BusinessRulesIFace busRule = DBTableIdMgr.getInstance().getBusinessRule(RecordSet.class);
                    if (busRule != null) {
                        busRule.beforeSave(batchRS, session);
                    }
                    batchRS.setTimestampCreated(new Timestamp(System.currentTimeMillis()));
                    batchRS.setOwner(AppContextMgr.getInstance().getClassObject(SpecifyUser.class));
                    session.beginTransaction();
                    transOpen = true;
                    session.save(batchRS);
                    if (busRule != null) {
                        if (!busRule.beforeSaveCommit(batchRS, session)) {
                            session.rollback();
                            throw new Exception("Business rules processing failed");
                        }
                    }
                    session.commit();
                    transOpen = false;
                    if (busRule != null) {
                        busRule.afterSaveCommit(batchRS, session);
                    }
                } catch (Exception ex) {
                    edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                    edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(Uploader.class, ex);
                    if (transOpen) {
                        session.rollback();
                    }
                }
            }

            /**
             * Add the batch RS to the RecordSetTask UI
             */
            protected void addBatchRSToUI() {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        CommandAction cmd = new CommandAction(RecordSetTask.RECORD_SET,
                                RecordSetTask.ADD_TO_NAV_BOX);
                        cmd.setData(batchRS);
                        CommandDispatcher.dispatch(cmd);
                    }
                });
            }

            /* (non-Javadoc)
             * @see javax.swing.SwingWorker#done()
             */
            @Override
            protected void done() {
                super.done();
                processingSeries.set(false);
                addBatchRSToUI();
                UIRegistry.clearSimpleGlassPaneMsg();
                if (objectsNotAdded.size() == 0) {
                    UIRegistry.displayLocalizedStatusBarText(BatchSaveSuccess,
                            formatter.formatToUI(catNumPair.getFirst()),
                            formatter.formatToUI(catNumPair.getSecond()));
                } else {
                    showBatchErrorObjects(objectsNotAdded, BatchSaveErrorsTitle, BatchSaveErrors);
                }
            }
        };

        final SimpleGlassPane gp = UIRegistry.writeSimpleGlassPaneMsg(getI10N("SAVING_BATCH"), 24);
        gp.setProgress(0);
        worker.addPropertyChangeListener(new PropertyChangeListener() {
            public void propertyChange(final PropertyChangeEvent evt) {
                if (GLASSKEY.equals(evt.getPropertyName())) {
                    double value = (double) ((Integer) evt.getNewValue()).intValue();
                    int percent = (int) (value / ((double) nums.size()) * 100.0);
                    gp.setProgress(percent);

                }
            }
        });
        processingSeries.set(true);
        worker.execute();
        //        try {
        //           worker.get();
        //        } catch (Exception ex) {
        //           ex.printStackTrace();
        //        }
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.specify.datamodel.busrules.BaseBusRules#okToDelete(java.lang.Object, edu.ku.brc.dbsupport.DataProviderSessionIFace, edu.ku.brc.ui.forms.BusinessRulesOkDeleteIFace)
     */
    @Override
    public void okToDelete(final Object dataObjArg, final DataProviderSessionIFace sessionArg,
            final BusinessRulesOkDeleteIFace deletable) {
        reasonList.clear();

        boolean isOK = true;
        if (deletable != null && dataObjArg instanceof FormDataObjIFace
                && ((FormDataObjIFace) dataObjArg).getId() != null) {
            Integer count = BasicSQLUtils
                    .getCount("SELECT COUNT(*) FROM collectionobject WHERE CollectionObjectID = "
                            + ((FormDataObjIFace) dataObjArg).getId());
            if (count != null && count == 0) {
                showLocalizedMsg("NO_RECORD_FOUND_TITLE", "NO_RECORD_FOUND");
                return;
            }

            Object dataObj = dataObjArg;
            DataProviderSessionIFace session = sessionArg != null ? sessionArg
                    : DataProviderFactory.getInstance().createSession();
            try {
                dataObj = session.merge(dataObj);

                CollectionObject colObj = (CollectionObject) dataObj;

                /*if (colObj.getAccession() != null)
                {
                isOK = false;
                addDeleteReason(Accession.getClassTableId());
                }*/

                if (isOK) {
                    // 03/25/09 rods - Added these extra null checks because of Bug 6848
                    // I can't reproduce it and these should never be null.
                    for (Preparation prep : colObj.getPreparations()) {
                        if (prep != null) {
                            if (prep.getLoanPreparations() != null && !prep.getLoanPreparations().isEmpty()) {
                                isOK = false;
                                addDeleteReason(LoanPreparation.getClassTableId());
                            }

                            if (prep.getDeaccessionPreparations() != null
                                    && !prep.getDeaccessionPreparations().isEmpty()) {
                                isOK = false;
                                addDeleteReason(DeaccessionPreparation.getClassTableId());
                            }

                            if (!isOK) {
                                break;
                            }
                        }
                    }
                }
            } catch (Exception ex) {
                edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(CollectionObjectBusRules.class, ex);
                ex.printStackTrace();
                // Error Dialog

            } finally {
                if (sessionArg == null && session != null) {
                    session.close();
                    session = null;
                }
            }

            deletable.doDeleteDataObj(dataObj, session, isOK);

        } else {
            super.okToDelete(dataObjArg, sessionArg, deletable);
        }
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.ui.forms.BaseBusRules#shouldCloneField(java.lang.String)
     */
    @Override
    public boolean shouldCloneField(String fieldName) {
        // Depending on the Type of Discipline the Collecting Events can be shared 
        // a ManyToOne from CollectionObject to Collecting (Fish).
        //
        // Or it acts like a OneToOne where each CE acts as if it is "embedded" or is
        // a part of the CO.
        //System.err.println(fieldName);
        Collection collection = AppContextMgr.getInstance().getClassObject(Collection.class);
        if (fieldName.equals("collectingEvent")) {
            // So we need to clone it make a full copy when it is embedded.
            return collection.getIsEmbeddedCollectingEvent();

        }

        Discipline discipline = AppContextMgr.getInstance().getClassObject(Discipline.class);
        if (fieldName.equals("paleoContext") && discipline.getIsPaleoContextEmbedded()
                && discipline.getPaleoContextChildTable().equalsIgnoreCase("collectionobject")) {
            if (discipline != null) {
                DisciplineType dt = DisciplineType.getByName(discipline.getType());
                if (dt != null && dt.isPaleo()) {
                    return true;
                }
            }
            return false;
        }

        if (fieldName.equals("collectionObjectAttribute")) {
            return true;
        }

        return false;
    }

    /**
     * @return true if the current entry is a series. (Including series of 1 object where startCatNum = 1 and endCatNum = 1.
     */
    protected boolean currentEntryIsASeries() {
        SeriesProcCatNumPlugin batchCtrl = getBatchPlugIn();
        return batchCtrl != null && batchCtrl.isExpanded();
    }

    /* (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 isEdit) {
        reasonList.clear();

        if (!(dataObj instanceof CollectionObject)) {
            return STATUS.Error;
        }

        STATUS duplicateNumberStatus = isCheckDuplicateNumberOK(CATNUMNAME, (FormDataObjIFace) dataObj,
                CollectionObject.class, "collectionObjectId");

        if (duplicateNumberStatus == STATUS.OK && checkFieldNumberDupl) {
            duplicateNumberStatus = checkForFieldNumDup(dataObj);
        }

        if (!processingSeries.get()) {
            //Now check series catnums, kind of awkward.
            return isCheckDuplicateBatchNumbersOK(!duplicateNumberStatus.equals(STATUS.OK));
        }

        return duplicateNumberStatus;
    }

    /**
     * @param dataObj
     * @return
     */
    private STATUS checkForFieldNumDup(final Object dataObj) {
        return isCheckDuplicateNumberOK("fieldNumber", (FormDataObjIFace) dataObj, CollectionObject.class,
                "collectionObjectId");
    }

    /* (non-Javadoc)
     * @see edu.ku.brc.af.ui.forms.BaseBusRules#isOkToAssociateSearchObject(java.lang.Object, java.lang.Object)
     */
    @Override
    public boolean isOkToAssociateSearchObject(Object parentdataObj, Object dataObjectFromSearch) {
        if (parentdataObj instanceof Accession) {
            reasonList.clear();

            Accession acc = (Accession) parentdataObj;
            CollectionObject colObj = (CollectionObject) dataObjectFromSearch;

            for (CollectionObject co : acc.getCollectionObjects()) {
                if (co.getId().equals(colObj.getId())) {
                    reasonList.add(getLocalizedMessage("CO_DUP", colObj.getIdentityTitle()));
                    return false;
                }
            }
        } else if (parentdataObj instanceof Project) {
            reasonList.clear();

            Project prj = (Project) parentdataObj;
            CollectionObject colObj = (CollectionObject) dataObjectFromSearch;

            for (CollectionObject co : prj.getCollectionObjects()) {
                if (co.getId().equals(colObj.getId())) {
                    reasonList.add(getLocalizedMessage("CO_DUP", colObj.getIdentityTitle()));
                    return false;
                }
            }
        }
        return true;
    }

    public static void fixDupColObjAttrs() {
        String sql = "SELECT * FROM (SELECT CollectionObjectAttributeID, count(*) as cnt FROM collectionobject c WHERE CollectionObjectAttributeID IS NOT NULL group by CollectionObjectAttributeID) T1 WHERE cnt > 1";
        Vector<Object[]> rows = BasicSQLUtils.query(sql);
        if (rows != null) {
            for (Object[] row : rows) {
                DataProviderSessionIFace session = null;
                try {
                    session = DataProviderFactory.getInstance().createSession();
                    CollectionObjectAttribute colObjAttr = session.get(CollectionObjectAttribute.class,
                            (Integer) row[1]);

                    int cnt = 0;
                    for (CollectionObject co : colObjAttr.getCollectionObjects()) {
                        if (cnt > 0) {
                            CollectionObjectAttribute colObjAttribute = (CollectionObjectAttribute) colObjAttr
                                    .clone();
                            co.setCollectionObjectAttribute(colObjAttribute);
                            colObjAttribute.getCollectionObjects().add(co);

                            session.beginTransaction();
                            session.saveOrUpdate(colObjAttribute);
                            session.saveOrUpdate(co);
                            session.commit();
                        }
                        cnt++;
                    }

                } catch (Exception ex) {
                    session.rollback();
                    ex.printStackTrace();
                } finally {
                    if (session != null) {
                        session.close();
                    }
                }
            }
        }
    }
}