Java tutorial
/* 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.af.ui.forms; import static edu.ku.brc.ui.UIHelper.createButton; import static edu.ku.brc.ui.UIHelper.createComboBox; import static edu.ku.brc.ui.UIHelper.setControlSize; import static edu.ku.brc.ui.UIRegistry.enableActionAndMenu; import static edu.ku.brc.ui.UIRegistry.getResourceString; import static org.apache.commons.lang.StringUtils.isEmpty; import static org.apache.commons.lang.StringUtils.isNotEmpty; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dialog; import java.awt.Font; import java.awt.Frame; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.sql.SQLException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ComboBoxModel; import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.KeyStroke; import javax.swing.ListModel; import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.hibernate.HibernateException; import org.hibernate.TypeMismatchException; import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.SQLGrammarException; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.debug.FormDebugPanel; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import edu.ku.brc.af.auth.PermissionSettings; import edu.ku.brc.af.auth.SecurityMgr; import edu.ku.brc.af.core.AppContextMgr; import edu.ku.brc.af.core.RecordSetFactory; import edu.ku.brc.af.core.SubPaneIFace; import edu.ku.brc.af.core.db.DBFieldInfo; import edu.ku.brc.af.core.db.DBInfoBase; import edu.ku.brc.af.core.db.DBRelationshipInfo; import edu.ku.brc.af.core.db.DBTableChildIFace; import edu.ku.brc.af.core.db.DBTableIdMgr; import edu.ku.brc.af.core.db.DBTableInfo; import edu.ku.brc.af.prefs.AppPreferences; import edu.ku.brc.af.prefs.AppPrefsCache; import edu.ku.brc.af.prefs.AppPrefsChangeEvent; import edu.ku.brc.af.prefs.AppPrefsChangeListener; import edu.ku.brc.af.ui.db.JAutoCompComboBox; import edu.ku.brc.af.ui.db.PickListItemIFace; import edu.ku.brc.af.ui.db.ViewBasedSearchDialogIFace; import edu.ku.brc.af.ui.forms.MultiView.ViewState; import edu.ku.brc.af.ui.forms.formatters.DataObjFieldFormatMgr; import edu.ku.brc.af.ui.forms.formatters.UIFieldFormatterIFace; import edu.ku.brc.af.ui.forms.formatters.UIFieldFormatterMgr; import edu.ku.brc.af.ui.forms.persist.AltViewIFace; import edu.ku.brc.af.ui.forms.persist.FormCell; import edu.ku.brc.af.ui.forms.persist.FormCellField; import edu.ku.brc.af.ui.forms.persist.FormCellFieldIFace; import edu.ku.brc.af.ui.forms.persist.FormCellIFace; import edu.ku.brc.af.ui.forms.persist.FormCellLabel; import edu.ku.brc.af.ui.forms.persist.FormCellSubView; import edu.ku.brc.af.ui.forms.persist.FormCellSubViewIFace; import edu.ku.brc.af.ui.forms.persist.FormDevHelper; import edu.ku.brc.af.ui.forms.persist.FormViewDef; import edu.ku.brc.af.ui.forms.persist.ViewDef; import edu.ku.brc.af.ui.forms.persist.ViewIFace; import edu.ku.brc.af.ui.forms.validation.AutoNumberableIFace; import edu.ku.brc.af.ui.forms.validation.DataChangeNotifier; import edu.ku.brc.af.ui.forms.validation.FormControlSaveable; import edu.ku.brc.af.ui.forms.validation.FormValidator; import edu.ku.brc.af.ui.forms.validation.FormValidatorInfo; import edu.ku.brc.af.ui.forms.validation.UIValidatable; import edu.ku.brc.af.ui.forms.validation.UIValidator; import edu.ku.brc.af.ui.forms.validation.ValFormattedTextFieldSingle; import edu.ku.brc.af.ui.forms.validation.ValidationListener; import edu.ku.brc.dbsupport.DataProviderFactory; import edu.ku.brc.dbsupport.DataProviderSessionIFace; import edu.ku.brc.dbsupport.RecordSetIFace; import edu.ku.brc.dbsupport.RecordSetItemIFace; import edu.ku.brc.dbsupport.SQLExecutionListener; import edu.ku.brc.dbsupport.SQLExecutionProcessor; import edu.ku.brc.dbsupport.StaleObjectException; import edu.ku.brc.helpers.SwingWorker; import edu.ku.brc.specify.datamodel.DataModelObjBase; import edu.ku.brc.ui.ColorChooser; import edu.ku.brc.ui.ColorWrapper; import edu.ku.brc.ui.CommandAction; import edu.ku.brc.ui.CommandDispatcher; import edu.ku.brc.ui.CustomDialog; import edu.ku.brc.ui.DateWrapper; import edu.ku.brc.ui.GetSetValueIFace; import edu.ku.brc.ui.IconManager; import edu.ku.brc.ui.ToggleButtonChooserDlg; import edu.ku.brc.ui.UIHelper; import edu.ku.brc.ui.UIRegistry; import edu.ku.brc.util.Orderable; import edu.ku.brc.util.Pair; /** * This implements a Form and is "owed" by a MultiView.<br> * <br> * Implementation of the Viewable interface for the ui and this derived class is for handling Form's Only (not tables).<br> * <br> * Implements ViewBuilderIFace which the ViewFactory uses while processing the rows, it calls methods in this interface * to add labels, controls and subforms to the form.<br> * <br> * Implements ValidationListener so it can listen to any and all validations so it knows how to show and activate the icon button * that enables the user to see what the errors are in a form.<br> * <br> * Implements ResultSetControllerListener to react to the record control bar for moving forward or backward in a resultset.<br> * <br> * Implements AppPrefsChangeListener to be notified of changes to the BG Required Field color or the date formatting. * * * @author rods * */ public class FormViewObj implements Viewable, ViewBuilderIFace, ValidationListener, ResultSetControllerListener, AppPrefsChangeListener, BusinessRulesOkDeleteIFace, PropertyChangeListener { private static final Logger log = Logger.getLogger(FormViewObj.class); private static final String actionName = "SwitcherToggle"; private static final String AUTO_NUM = "AutoNumbering"; protected enum SAVE_STATE { Initial, NewObjSaveerror, StaleRecovery, SaveOK, Error } // Static Data Members protected static Object[] formattedValues = new Object[2]; protected static ColorWrapper viewFieldColor = null; protected static CellConstraints cc = new CellConstraints(); protected static boolean useDebugForm = false; public static final String STATUSBAR_NAME = "FormViewObj"; // Data Members protected DataProviderSessionIFace session = null; protected Vector<SessionListenerIFace> sessionListeners = null; protected boolean isEditing = false; protected boolean isNewlyCreatedDataObj = false; protected boolean isCreatingNewObject = false; // true when in the middle of creating a new Object protected MultiView mvParent = null; protected ViewIFace view; protected AltViewIFace altView; protected FormViewDef formViewDef; protected String cellName; protected Component formComp = null; protected List<MultiView> kids = new ArrayList<MultiView>(); protected Vector<AltViewIFace> altViewsList = null; protected Class<?> classToCreate = null; protected ArrayList<FVOFieldInfo> compsList = new ArrayList<FVOFieldInfo>(); protected Hashtable<String, FVOFieldInfo> controlsById = new Hashtable<String, FVOFieldInfo>(); protected Hashtable<String, FVOFieldInfo> controlsByName = new Hashtable<String, FVOFieldInfo>(); protected Hashtable<String, FVOFieldInfo> labels = new Hashtable<String, FVOFieldInfo>(); // ID is the Key protected Hashtable<String, JLabel> allLabels = new Hashtable<String, JLabel>(); // ID is the Key protected ArrayList<FormControlSaveable> saveableList = new ArrayList<FormControlSaveable>(); protected ArrayList<UIPluginable> uiPlugins = new ArrayList<UIPluginable>(); protected FormLayout formLayout; protected PanelBuilder builder; protected boolean isBuildValid = false; protected boolean hasRequiredFields = false; protected boolean isSkippingAttach = false; // Indicates whether to skip before setting data into the form protected Boolean isJavaCollection = null; protected FormValidator formValidator = null; protected Object parentDataObj = null; protected Object dataObj = null; protected Set<Object> origDataSet = null; protected Object[] singleItemArray = new Object[1]; protected DateWrapper scrDateFormat; protected int options; protected boolean isAlwaysGetDataFromUI = false; protected JPanel mainComp = null; protected ControlBarPanel controlPanel = null; protected ResultSetController rsController = null; protected Vector<Object> list = null; protected boolean ignoreSelection = false; protected JComponent saveControl = null; protected JButton newRecBtn = null; protected JButton delRecBtn = null; protected boolean wasNull = false; protected MenuSwitcherPanel switcherUI; protected int mainCompRowInx = 1; protected boolean saveAndNew = false; protected boolean isAutoNumberOn = true; protected RestrictablePanel restrictablePanel = null; protected JPanel sepController = null; protected boolean doingDiscard = false; protected String searchName = null; protected JButton srchRecBtn = null; // When creating a new Data Object protected Object oldDataObj = null; protected boolean doSetIntoAndValidate = true; // Forms that have a Selector protected JComboBox<?> selectorCBX = null; protected boolean isSelectorForm; protected boolean isShowing = false; protected BusinessRulesIFace businessRules = null; protected boolean hasInitBR = false; protected Class<?> dataClass; protected DraggableRecordIdentifier draggableRecIdentifier = null; // Carry Forward protected CarryForwardInfo carryFwdInfo = null; protected boolean doCarryForward = false; protected Object carryFwdDataObj = null; // RecordSet Management protected RecordSetIFace recordSet = null; protected List<RecordSetItemIFace> recordSetItemList = null; protected DBTableInfo tableInfo = null; protected Color bgColor = null; protected Vector<ViewState> viewStateList = null; // Security private PermissionSettings perm = null; /** * Constructor with FormView definition. * @param view the definition of the view * @param altView indicates which AltViewIFace we will be using * @param mvParent the mvParent multiview * @param createResultSetController indicates that a ResultSet Controller should be created * @param formValidator the form's formValidator * @param options the options needed for creating the form * @param bgColor bg color it should use */ /*public FormViewObj(final ViewIFace view, final AltViewIFace altView, final MultiView mvParent, final FormValidator formValidator, final int options, final Color bgColor) { this(view, altView, mvParent, formValidator, options, null, bgColor); }*/ /** * Constructor with FormView definition. * @param view the definition of the view * @param altView indicates which AltViewIFace we will be using * @param mvParent the mvParent mulitview * @param formValidator the form's formValidator * @param options the options needed for creating the form * @param cellName the name of the outer form's cell for this view (subview) * @param bgColor bg color it should use */ public FormViewObj(final ViewIFace view, final AltViewIFace altView, final MultiView mvParent, final FormValidator formValidator, final int options, final String cellName, final Class<?> dataClass, final Color bgColor) { this.view = view; this.altView = altView; this.mvParent = mvParent; this.cellName = cellName; this.dataClass = dataClass; this.bgColor = bgColor; businessRules = view.createBusinessRule(); //XXX bug #9497: isEditing = altView.getMode() == AltViewIFace.CreationMode.EDIT && MultiView.isOptionOn(options, MultiView.IS_EDITTING); isEditing = altView.getMode() == AltViewIFace.CreationMode.EDIT; boolean addSearch = mvParent != null && MultiView.isOptionOn(mvParent.getOptions(), MultiView.ADD_SEARCH_BTN); if (addSearch) { isEditing = false; } this.formViewDef = (FormViewDef) altView.getViewDef(); // Figure columns try { JPanel panel = useDebugForm ? new FormDebugPanel() : (restrictablePanel = new RestrictablePanel()); formLayout = new FormLayout(formViewDef.getColumnDef(), formViewDef.getRowDef()); builder = new PanelBuilder(formLayout, panel); } catch (java.lang.NumberFormatException ex) { String msg = "Error in row or column definition for form: `" + view.getName() + "`\n" + ex.getMessage(); UIRegistry.showError(msg); return; } mainComp = new JPanel(new BorderLayout()); mainComp.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); if (mvParent == null) { builder.getPanel().setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); } if (bgColor != null) { builder.getPanel().setBackground(bgColor); } this.options = options; boolean isSingleObj = MultiView.isOptionOn(options, MultiView.IS_SINGLE_OBJ); boolean createResultSetController = MultiView.isOptionOn(options, MultiView.RESULTSET_CONTROLLER); boolean hideResultSetController = MultiView.isOptionOn(options, MultiView.HIDE_RESULTSET_CONTROLLER); boolean createViewSwitcher = MultiView.isOptionOn(options, MultiView.VIEW_SWITCHER); //boolean isNewObject = MultiView.isOptionOn(options, MultiView.IS_NEW_OBJECT); boolean hideSaveBtn = MultiView.isOptionOn(options, MultiView.HIDE_SAVE_BTN); isNewlyCreatedDataObj = MultiView.isOptionOn(options, MultiView.IS_NEW_OBJECT); if (formValidator != null) { formValidator.setNewObj(isNewlyCreatedDataObj); } //MultiView.printCreateOptions("Creating Form "+altView.getName(), options); setValidator(formValidator); scrDateFormat = AppPrefsCache.getDateWrapper("ui", "formatting", "scrdateformat"); AppPreferences.getRemote().addChangeListener("ui.formatting.viewfieldcolor", this); boolean addController = mvParent != null && view.getAltViews().size() > 1; // See if we need to add a Selector ComboBox isSelectorForm = StringUtils.isNotEmpty(view.getSelectorName()); boolean addSelectorCBX = false; //log.debug(altView.getName()+" "+altView.getMode()+" "+AltViewIFace.CreationMode.EDIT); //if (isSelectorForm && isNewObject && altView.getMode() == AltViewIFace.CreationMode.EDIT) if (isSelectorForm && altView.getMode() == AltViewIFace.CreationMode.EDIT) { addSelectorCBX = true; } List<JComponent> comps = new ArrayList<JComponent>(); int y = 1; // Here we create the JComboBox that enables the user to switch between forms // when creating a new object if (addSelectorCBX) { Vector<AltViewIFace> cbxList = new Vector<AltViewIFace>(); cbxList.add(altView); for (AltViewIFace av : view.getAltViews()) { if (av != altView && av.getMode() == AltViewIFace.CreationMode.EDIT) { cbxList.add(av); } } JPanel p = new JPanel(new BorderLayout()); p.setOpaque(false); p.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); selectorCBX = createComboBox(cbxList); selectorCBX.setRenderer(new SelectorCellRenderer()); p.add(selectorCBX, BorderLayout.WEST); mainComp.add(p, BorderLayout.NORTH); if (mvParent != null) { selectorCBX.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { doSelectorWasSelected(mvParent, ev); } }); } y += 2; } // // We will add the switchable UI if we are parented to a MultiView and have multiple AltViews // if (addController) // this says we are the "root" form { boolean saveWasAdded = false; // We want it on the left side of other buttons // so wee need to add it before the Save button JComponent valInfoBtn = createValidationIndicator(getUIComponent(), formValidator); if (valInfoBtn != null) { comps.add(valInfoBtn); } if (createViewSwitcher) // This is passed in outside { // Now we have a Special case that when when there are only two AltViews and // they differ only by Edit & View we hide the switching UI unless we are the root MultiView. // This way when switching the Root View all the other views switch // (This is because they were created that way. It also makes no sense that while in "View" mode // you would want to switch an individual subview to a differe "mode" view than the root). altViewsList = new Vector<AltViewIFace>(); // This will return null if it isn't suppose to have a switcher switcherUI = createMenuSwitcherPanel(mvParent, view, altView, altViewsList, restrictablePanel, cellName, dataClass); Action action = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (switcherUI != null && switcherUI.getSwitcherAL() != null) { switcherUI.getSwitcherAL().actionPerformed(e); } } }; if (restrictablePanel != null) { restrictablePanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) .put(KeyStroke.getKeyStroke("control E"), actionName); restrictablePanel.getActionMap().put(actionName, action); } if (altViewsList.size() > 0) { if (altView.getMode() == AltViewIFace.CreationMode.EDIT && mvParent != null && mvParent.isTopLevel()) { addSaveBtn(); comps.add(saveControl); saveWasAdded = true; } if (switcherUI != null) { comps.add(switcherUI); } } // rods - 07/21/08 for disabling the switcher when the form is invalid if (formValidator != null && switcherUI != null) { formValidator.addEnableItem(switcherUI, FormValidator.EnableType.ValidNotNew); } } if (!saveWasAdded && altView.getMode() == AltViewIFace.CreationMode.EDIT && mvParent != null && mvParent.isTopLevel() && !hideSaveBtn) { addSaveBtn(); comps.add(saveControl); } } // This here because the Search mode shouldn't be combined with other modes if (altView.getMode() == AltViewIFace.CreationMode.SEARCH) { if (!hideSaveBtn) { saveControl = createButton(UIRegistry.getResourceString("SEARCH"), IconManager.getImage("Search", IconManager.IconSize.Std16));/* { public void setEnabled(boolean enabled) { System.err.println("Save: "+enabled); super.setEnabled(enabled); } };*/ saveControl.setOpaque(false); comps.add(saveControl); addSaveActionMap(saveControl); } } if (ViewFactory.isFormTransparent()) { builder.getPanel().setOpaque(false); } mainComp.add(builder.getPanel(), BorderLayout.CENTER); if (comps.size() > 0 || addController || createResultSetController) { controlPanel = new ControlBarPanel(bgColor); controlPanel.addComponents(comps, false); // false -> right side if (ViewFactory.isFormTransparent()) { controlPanel.setOpaque(false); } mainComp.add(controlPanel, BorderLayout.SOUTH); } if (createResultSetController) { addRSController(addSearch); if (hideResultSetController) { rsController.getPanel().setVisible(false); } if (addSearch) { DBTableInfo tblInfo = DBTableIdMgr.getInstance().getByClassName(view.getClassName()); if (tblInfo != null) { searchName = tblInfo.getSearchDialog(); if (StringUtils.isEmpty(searchName)) { searchName = ""; // Note not null but empty tells it to disable the search btn log.error("The Search Dialog Name is empty or missing for class[" + view.getClassName() + "]"); } } else { log.error("Couldn't find TableInfo for class[" + view.getClassName() + "]"); } if (rsController.getSearchRecBtn() != null) { rsController.getSearchRecBtn().setEnabled(true); rsController.getSearchRecBtn().addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { doSearch(); } }); } } } else if (isSingleObj) { createAddDelSearchPanel(); } if (true) { builder.getPanel().addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { showContextMenu(e); } @Override public void mouseReleased(MouseEvent e) { showContextMenu(e); } @Override public void mouseClicked(MouseEvent e) { //FormViewObj.this.listFieldChanges(); } }); } if (rsController != null) { rsController.setNewObj(isNewlyCreatedDataObj); } isBuildValid = true; isAutoNumberOn = AppPreferences.getLocalPrefs().getBoolean(AUTO_NUM, true); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { updateAutoNumberFieldState(); } }); } /** * Register the KeyBinding short cut for the Save control * @param saveComp the save control */ private void addSaveActionMap(final JComponent saveComp) { UIHelper.addSaveKeyBinding(saveComp, new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { saveOnThread(saveAndNew); } }); } /** * @return the isBuildValid */ public boolean isBuildValid() { return isBuildValid; } /** * Helper method for discovering the type of objects it will hold. */ protected boolean isJavaCollection() { if (parentDataObj != null) { if (isJavaCollection == null) { isJavaCollection = false; DBTableInfo ti = DBTableIdMgr.getInstance().getByClassName(parentDataObj.getClass().getName()); if (ti != null) { DBRelationshipInfo ri = ti.getRelationshipByName(cellName); if (ri != null) { //log.debug(ri.getType()); isJavaCollection = ri.getType() == DBRelationshipInfo.RelationshipType.OneToMany || ri.getType() == DBRelationshipInfo.RelationshipType.ManyToMany; } } } return isJavaCollection; } return false; } /** * @return the cellName */ public String getCellName() { return cellName; } /** * @param mv * @param ev */ protected void doSelectorWasSelected(final MultiView mv, final ActionEvent ev) { if (!ignoreSelection) { AltViewIFace selectedAV = (AltViewIFace) ((JComboBox) ev.getSource()).getSelectedItem(); // Transfer the data from old form to the new form. traverseToGetDataFromForms(mvParent); Object dObj = mv.getData(); mv.showView(selectedAV.getName()); mv.setData(dObj); mv.validateAll(); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#setClassToCreate(java.lang.String) */ public void setClassToCreate(final Class<?> classToCreate) { this.classToCreate = classToCreate; } /** * @return the newRecBtn */ public JButton getNewRecBtn() { return newRecBtn; } /** * @return the delRecBtn */ public JButton getDelRecBtn() { return delRecBtn; } /** * Creates a special drop "switcher UI" component for switching between the Viewables in the MultiView. * @param mvParentArg the MultiView Parent * @param viewArg the View * @param altViewArg the AltViewIFace * @param altViewsListArg the Vector of AltViewIFace that will contains the ones in the Drop Down * @return the special combobox * @param restrictableUI * @param cellName the name of the cell when it is a subview * @param dataClass the class of the data that is put into the form * @return */ public static MenuSwitcherPanel createMenuSwitcherPanel(final MultiView mvParentArg, final ViewIFace viewArg, final AltViewIFace altViewArg, final Vector<AltViewIFace> altViewsListArg, final RestrictableUIIFace restrictableUI, final String cellName, final Class<?> dataClass) { if (AppContextMgr.isSecurityOn()) { PermissionSettings perm = MultiView.getPremissionFromView(viewArg, MultiView.getClassNameFromParentMV(dataClass, mvParentArg, cellName)); //PermissionSettings.dumpPermissions(mvParentArg.getViewName(), perm.getOptions()); if (perm.hasNoPerm() && restrictableUI != null) { restrictableUI.setRestricted(true); } AltViewIFace.CreationMode mode = altViewArg.getMode(); for (AltViewIFace av : viewArg.getAltViews()) { boolean isSecurityModeOK = perm.getOptions() > 0 && ((perm.isViewOnly() && (mode == AltViewIFace.CreationMode.VIEW)) || !perm.isViewOnly()); //PermissionSettings.dumpPermissions(viewArg.getClassName()+" "+isSecurityModeOK+" "+av.getTitle()+" "+mode, perm.getOptions()); if (isSecurityModeOK && (av.getMode() == mode || (mvParentArg.isTopLevel() && mvParentArg.isOKToAddAllAltViews()))) { altViewsListArg.add(av); } } } else { // Add all the View if we are at the top level // If not, then we are a subform and we should only add the view that belong to our same creation mode. if (mvParentArg.isTopLevel() && mvParentArg.isOKToAddAllAltViews()) { altViewsListArg.addAll(viewArg.getAltViews()); } else { AltViewIFace.CreationMode mode = altViewArg.getMode(); for (AltViewIFace av : viewArg.getAltViews()) { if (av.getMode() == mode) { altViewsListArg.add(av); } } } } return altViewsListArg.size() > 1 ? new MenuSwitcherPanel(mvParentArg, altViewArg, altViewsListArg) : null; } /** * @return the saveAndNew */ public boolean isSaveAndNew() { return saveAndNew; } /** * @param saveAndNew the saveAndNew to set */ public void setSaveAndNew(boolean saveAndNew) { this.saveAndNew = saveAndNew; if (saveControl instanceof JButton) { ((JButton) saveControl).setText(getResourceString(saveAndNew ? "SAVE_AND_NEW_BTN" : "Save")); } } /** * Adds the Save Button to the form. */ protected void addSaveBtn() { JButton saveBtn; boolean doDebug = false; if (!doDebug) { saveBtn = createButton(UIRegistry.getResourceString("SAVE")); } else { saveBtn = new JButton(UIRegistry.getResourceString("SAVE")) { public void setEnabled(boolean enabled) { //if (enabled) log.debug("******* "+formValidator.getName()+" Save: "+enabled); super.setEnabled(enabled); } }; } saveBtn.setEnabled(false); saveBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { saveOnThread(saveAndNew); } }); saveControl = saveBtn; addSaveActionMap(saveControl); if (formValidator != null) { formValidator.setSaveComp(saveBtn, FormValidator.EnableType.ValidAndChangedItems); } } /** * Returns the CarryForwardInfo Object for the Form. * @return the CarryForwardInfo Object for the Form */ private CarryForwardInfo getCarryForwardInfo() { if (carryFwdInfo == null) { try { Class<?> classObj = Class.forName(formViewDef.getClassName()); carryFwdInfo = new CarryForwardInfo(classObj, this, formViewDef); } catch (ClassNotFoundException ex) { FormDevHelper.showFormDevError(ex); } } return carryFwdInfo; } /** * Returns whether this form is doing Carry Forward. * @return whether this form is doing Carry Forward */ public boolean isDoCarryForward() { return doCarryForward; } /** * Turns on/off Carry Forward for this form * @param doCarryForward true - on, false - off */ public void setDoCarryForward(boolean doCarryForward) { this.doCarryForward = doCarryForward; adjustActionsAndMenus(true); } /** * @return returns whether there is any set up information. */ public boolean isCarryForwardConfgured() { if (carryFwdInfo != null) { return carryFwdInfo.hasConfiguredFields(); } return false; } /** * Adjust the Action and MenuItem for CarryForward. * @param isVisible whether is is visible */ private void adjustActionsAndMenus(final boolean isVisibleArg) { // Temporary fix for Bug 7231 // A call to showView get put out on the event queue for other reasons // and with a closeAll happening that call to show comes after the // call to hide it. This is great, what needs to be fixed // is not putting the call to showView on the event thread. // the call is made in 'aboutToShow' boolean isVisible = isVisibleArg; if (isVisible) { Component p = mainComp.getParent(); while (p != null && !(p instanceof SubPaneIFace)) { p = p.getParent(); } // it isn't in the TabbedPane if the parent is null if (p != null && p instanceof SubPaneIFace && p.getParent() == null) { isVisible = false; } } // done with temporary fix boolean isConfiged = isCarryForwardConfgured() && isVisible; enableActionAndMenu("CarryForward", isConfiged, isConfiged); enableActionAndMenu("ConfigCarryForward", isVisible, null); boolean doAutoNum = isAutoNumberOn() && isEditing && isVisible; enableActionAndMenu(AUTO_NUM, isEditing && isVisible, doAutoNum); enableActionAndMenu("SaveAndNew", isVisible, null); } /** * @param itemLabels * @param tblInfo */ private void buildFieldInfoList(Vector<FVOFieldInfo> itemLabels, final DBTableInfo tblInfo) { // This next section loops through all the UI components in the form that has an ID // It checks to make sure that it is a candidate for CF Vector<String> ids = new Vector<String>(); getFieldIds(ids, true); // true means return all the UI components with ids not just the fields for (String id : ids) { FVOFieldInfo fieldInfo = getFieldInfoForId(id); String fieldName = fieldInfo.getFormCell().getName(); DBFieldInfo fi = tblInfo != null ? tblInfo.getFieldByName(fieldName) : null; fieldInfo.setFieldInfo(fi); log.debug("-------------------------------"); log.debug(fieldName); // Start by assuming it is OK to be added boolean isOK = true; if (fieldInfo.getFormCell() instanceof FormCellFieldIFace) { // Only the ones that are editable. FormCellFieldIFace fcf = (FormCellFieldIFace) fieldInfo.getFormCell(); if (fcf.isReadOnly()) { isOK = false; } else { DBInfoBase infoBase = fieldInfo.getFieldInfo(); if (infoBase instanceof DBFieldInfo) { if (fi.isUnique() || !fi.isUpdatable()) { isOK = false; } else if (fi.getFormatter() != null && fi.getFormatter().isIncrementer()) { isOK = false; } } else { log.debug("Skipping " + infoBase); } } } else { log.debug("Skipping " + fieldInfo.getFormCell()); } // At this point we have weeded out any readonly/autoinc "fields" and we need to get a label for the field // And weed out any SubViews. if (isOK) { // Check to see if the field has a label String label = null; FVOFieldInfo labelInfo = getLabelInfoFor(id); if (labelInfo != null) { if (!(fieldInfo.getFormCell() instanceof FormCellLabel)) { label = ((FormCellLabel) labelInfo.getFormCell()).getLabel(); } } //log.debug("Field ["+fieldName+"] in ["+(ti != null ? ti.getTitle() : "N/A")+"]"); // Now we go get the DBFieldInfo and DBRelationshipInfo and check to make // that the field or Relationship is still a candidate for CF DBInfoBase infoBase = null; if (tblInfo != null) { if (fi != null) { infoBase = fi; // Skip any fields that are AutoNumbered if (fieldInfo.getComp() instanceof AutoNumberableIFace) { isOK = !((AutoNumberableIFace) fieldInfo.getComp()).isFormatterAutoNumber(); } else { isOK = true; } } else { DBRelationshipInfo ri = tblInfo.getRelationshipByName(fieldName); if (ri != null) { infoBase = ri; // If the field is a OneToMany then it is a s Set // and we need to make sure the items in the set are clonable // if they are not clonable then we can't include this in // the Carry Forward list Class<?> dataCls = ri.getDataClass(); if (ri.getType() == DBRelationshipInfo.RelationshipType.OneToMany) { try { Method method = dataCls.getMethod("clone", new Class<?>[] {}); // Pretty much every Object has a "clone" method but we need // to check to make sure it is implemented by the same class of // Object that is in the Set. isOK = method.getDeclaringClass() == dataCls; } catch (Exception ex) { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex); isOK = false; // this really shouldn't happen } } } else if (fieldInfo.getUiPlugin() != null) { if (StringUtils.isNotEmpty(label)) { label = fieldInfo.getUiPlugin().getTitle(); } isOK = fieldInfo.getUiPlugin().canCarryForward(); } else { log.error("Couldn't find field [" + fieldName + "] in [" + tblInfo.getTitle() + "]"); isOK = false; } } if (isOK) { if (infoBase != null && StringUtils.isEmpty(label)) { label = infoBase.getTitle(); } fieldInfo.setLabel(label); itemLabels.add(fieldInfo); fieldInfo.setFieldInfo(infoBase); } else { log.error("Field NOT OK [" + fieldName + "] in [" + tblInfo.getTitle() + "]"); } } } } Collections.sort(itemLabels, new Comparator<FVOFieldInfo>() { @Override public int compare(FVOFieldInfo o1, FVOFieldInfo o2) { if (o1.getLabel() == null || o2.getLabel() == null) { return 1; } return o1.getLabel().compareTo(o2.getLabel()); } }); } /** * Shows a Dialog to setup Carry Forward. * The hard part is figuring out which fields are candidates for Carry Forward. */ public void configureCarryForward() { CarryForwardInfo carryForwardInfo = getCarryForwardInfo(); DBTableInfo tblInfo = DBTableIdMgr.getInstance().getByClassName(view.getClassName()); Vector<FVOFieldInfo> itemLabels = new Vector<FVOFieldInfo>(); Vector<FVOFieldInfo> selectedItems = new Vector<FVOFieldInfo>(carryForwardInfo.getFieldList()); buildFieldInfoList(itemLabels, tblInfo); ToggleButtonChooserDlg<FVOFieldInfo> dlg = new ToggleButtonChooserDlg<FVOFieldInfo>( (Frame) UIRegistry.getTopWindow(), "CONFIG_CARRY_FORWARD_TITLE", itemLabels); dlg.setUseScrollPane(true); dlg.setAddSelectAll(true); dlg.createUI(); HashMap<String, JToggleButton> tgBtnHash = new HashMap<String, JToggleButton>(); Vector<JToggleButton> btns = dlg.getPanel().getButtons(); for (JToggleButton tb : btns) { tgBtnHash.put(tb.getText(), tb); } for (FVOFieldInfo itm : itemLabels) { if (itm.isRequired()) { JToggleButton togBtn = tgBtnHash.get(itm.getLabel()); if (togBtn != null) { togBtn.setEnabled(false); selectedItems.add(itm); } } } dlg.setSelectedObjects(selectedItems); UIHelper.centerAndShow(dlg); if (!dlg.isCancelled()) { carryForwardInfo.add(dlg.getSelectedObjects()); } notifyUIPluginsOfChanges(true, null); } /** * Toggles Carry Forward State (Turning it on and off). */ public void toggleCarryForward() { setDoCarryForward(!isDoCarryForward()); JCheckBoxMenuItem mi = (JCheckBoxMenuItem) UIRegistry.get("CarryForward"); if (mi != null) { mi.setSelected(isDoCarryForward()); } } /** * @param doStateUpdate * @param isNewFormObj */ private void notifyUIPluginsOfChanges(final boolean doStateUpdate, final Boolean isNewFormObj) { for (UIPluginable plugin : uiPlugins) { if (doStateUpdate) { plugin.carryForwardStateChange(); } else if (isNewFormObj != null) { plugin.setNewObj(isNewFormObj); } } } /** * Shows Parent Form's Context Menu. * @param e the mouse event */ protected void showContextMenu(MouseEvent e) { if (e.isPopupTrigger() && mvParent != null && mvParent.isTopLevel() && isEditing) { JPopupMenu popup = new JPopupMenu(); JMenuItem menuItem = new JMenuItem(UIRegistry.getResourceString("CONFIG_CARRY_FORWARD_MENU")); menuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ex) { configureCarryForward(); } }); popup.add(menuItem); JCheckBoxMenuItem chkMI = new JCheckBoxMenuItem( UIRegistry.getResourceString("CARRY_FORWARD_CHECKED_MENU")); chkMI.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ex) { toggleCarryForward(); } }); chkMI.setSelected(isCarryForwardConfgured() && isDoCarryForward()); chkMI.setEnabled(isCarryForwardConfgured()); popup.add(chkMI); popup.addSeparator(); chkMI = new JCheckBoxMenuItem(UIRegistry.getAction(AUTO_NUM)); /*chkMI.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ex) { toggleAutoNumberOnOffState(); } });*/ chkMI.setSelected(isAutoNumberOn); popup.add(chkMI); popup.show(e.getComponent(), e.getX(), e.getY()); } } /** * Toggles Auto-Numbering mode (turns on or off). */ public void toggleAutoNumberOnOffState() { isAutoNumberOn = !isAutoNumberOn; AppPreferences.getLocalPrefs().putBoolean(AUTO_NUM, isAutoNumberOn); updateAutoNumberFieldState(); } /** * Updates the AutoNumbering Menu and the control on the form. */ protected void updateAutoNumberFieldState() { JCheckBoxMenuItem mi = (JCheckBoxMenuItem) UIRegistry.get(AUTO_NUM); if (mi != null) { mi.setSelected(isAutoNumberOn); } for (FVOFieldInfo fieldInfo : controlsById.values()) { Component comp = fieldInfo.getComp(); if (comp instanceof AutoNumberableIFace) { ((AutoNumberableIFace) comp).setAutoNumberEnabled(isAutoNumberOn); } } } /** * @return the entire list of controls. */ public List<FVOFieldInfo> getComps() { return compsList; } /** * @return the isAutoNumberOn */ public boolean isAutoNumberOn() { return isAutoNumberOn; } /** * Creates the JButton that displays the current state of the forms validation * @param window * @param validator * @return */ public static JButton createValidationIndicator(final Component comp, final FormValidator validator) { if (validator != null) { JButton validationInfoBtn = new JButton(IconManager.getIcon("ValidationValid")); validationInfoBtn.setOpaque(false); validationInfoBtn.setToolTipText(getResourceString("SHOW_VALIDATION_INFO_TT")); validationInfoBtn.setMargin(new Insets(1, 1, 1, 1)); validationInfoBtn.setBorder(BorderFactory.createEmptyBorder()); validationInfoBtn.setFocusable(false); validationInfoBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { showValidationInfo(comp instanceof Window ? (Window) comp : UIHelper.getWindow(comp), validator); } }); validator.setValidationBtn(validationInfoBtn); return validationInfoBtn; } // else return null; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.Viewable#getMVParent() */ @Override public MultiView getMVParent() { return mvParent; } /** * Static Helper method for showing Validation info. * @param viewable the view to show info for. */ protected static void showValidationInfo(final Window window, final FormValidator validator) { final FormValidatorInfo formInfo = new FormValidatorInfo(validator); PanelBuilder panelBuilder = new PanelBuilder(new FormLayout("p", "p,5px,p")); panelBuilder.add(formInfo, cc.xy(1, 1)); CustomDialog dialog; if (window instanceof JDialog) { dialog = new CustomDialog((Dialog) window, validator.getName(), true, CustomDialog.OK_BTN, panelBuilder.getPanel()) { @Override public void setVisible(final boolean visible) { if (!visible) { formInfo.cleanUp(); } super.setVisible(visible); } }; } else { dialog = new CustomDialog((Frame) window, validator.getName(), true, CustomDialog.OK_BTN, panelBuilder.getPanel()) { @Override public void setVisible(final boolean visible) { if (!visible) { formInfo.cleanUp(); } super.setVisible(visible); } }; } dialog.setOkLabel(getResourceString("CLOSE")); UIHelper.centerAndShow(dialog); dialog.dispose(); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#aboutToShow(boolean) */ public void aboutToShow(final boolean show) { isShowing = show; /*if (origDataSet != null && list != null && origDataSet.size() != list.size()) { // XXX Ok here we know new items have been added // so we need to resort (maybe) but certainly need to re-adjust the RecordSet controller. // // Actually check the sizes isn't enough, we need to really know if there was a change in the list }*/ if (formValidator != null) { formValidator.validateForm(); } if (switcherUI != null) { ignoreSelection = true; switcherUI.set(altView); ignoreSelection = false; } if (selectorCBX != null) { ignoreSelection = true; selectorCBX.setEnabled(true); selectorCBX.setSelectedIndex(0); ignoreSelection = false; } for (MultiView mv : kids) { mv.aboutToShow(show); } if (mvParent != null && mvParent.isTopLevel() && isEditing) { if (show) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { //log.error(hashCode()+" "+show); adjustActionsAndMenus(true); } }); } else { //log.error(hashCode()+" "+show); adjustActionsAndMenus(false); } } // Give all the ResultSetController btns one last chance with all the data there to be enabled SwingUtilities.invokeLater(new Runnable() { @Override public void run() { updateControllerUI(); } }); // Moving this to the MultiView /*if (show) { log.debug("Dispatching a Data_Entry/ViewWasShown command/action"); CommandDispatcher.dispatch(new CommandAction("Data_Entry", "ViewWasShown", this)); }*/ } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getViewDef() */ public FormViewDef getViewDef() { return formViewDef; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getAltView() */ public AltViewIFace getAltView() { return altView; } /** * Returns the name of the form from the FormView * @return the name of the form from the FormView */ public String getName() { return formViewDef.getName(); } /** * Returns the current Data Object, which means the actual object if it is not a list * or the current object in the list * @return Returns the current Data Object, which means the actual object if it is not a list * or the current object in the list */ public Object getCurrentDataObj() { return dataObj; } /** * Return list of data objects if this is a recordset * @return the list of data objects */ public List<?> getDataList() { return list; } /** * Sets the component into the object * @param formComp the UI component that represents this viewable */ public void setFormComp(final JComponent formComp) { // Remove existing component if (this.formComp != null) { mainComp.remove(this.formComp); } // add new component if (MultiView.isOptionOn(options, MultiView.NO_SCROLLBARS)) { if (ViewFactory.isFormTransparent()) { formComp.setOpaque(false); } this.mainComp.add(formComp, BorderLayout.CENTER); this.formComp = formComp; } else { JScrollPane scrollPane = new JScrollPane(formComp, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPane.getVerticalScrollBar().setUnitIncrement(10); scrollPane.setBorder(null); this.mainComp.add(scrollPane, BorderLayout.CENTER); this.formComp = scrollPane; if (ViewFactory.isFormTransparent()) { scrollPane.setOpaque(false); scrollPane.getViewport().setOpaque(false); } } if (businessRules != null && !hasInitBR) { businessRules.initialize(this); hasInitBR = true; } // This is needed to make the form layout correctly //XXX I hate that I have to do this SwingUtilities.invokeLater(new Runnable() { public void run() { //mainComp.invalidate(); //mainComp.validate(); //mainComp.doLayout(); UIRegistry.forceTopFrameRepaint(); } }); } /** * Returns the panel that contains all the controls. * @return the panel that contains all the controls */ public JPanel getPanel() { return builder.getPanel(); } /** * Adds child to mvParent * @param child the child to be added */ public void addChild(final MultiView child) { kids.add(child); } /** * Sets the multiview if it is owned or mvParented by it. * @param cbx combobox to add a listener to */ public void addMultiViewListener(final JComboBox cbx) { class MVActionListener implements ActionListener { protected MultiView mv; public MVActionListener(final MultiView mv) { this.mv = mv; } public void actionPerformed(ActionEvent ae) { doSelectorWasSelected(mv, ae); } } if (cbx != null) { cbx.addActionListener(new MVActionListener(mvParent)); } } /** * Set the form formValidator and hooks up the root form to listen also. * @param formValidator the formValidator */ protected void setValidator(final FormValidator formValidator) { if (this.formValidator != null) { this.formValidator.removeValidationListener(this); } this.formValidator = formValidator; // If there is a form validator and this is not the "root" form // then add this form as a listener to the validator AND // make the root form a listener to this validator. if (formValidator != null && mvParent != null) { formValidator.addValidationListener(this); } } /** * Adds new child object to its parent to a Set * @param newDataObj the new object to be added to a Set */ protected static void removeFromParent(final MultiView mvParent, final Object parentDataObjArg, final String cellNameArg, final Object oldDataObjArg) { if (oldDataObjArg != null) { if (parentDataObjArg != null) { log.debug("Removing " + oldDataObjArg + " " + oldDataObjArg.getClass().getSimpleName() + " from " + parentDataObjArg); if (parentDataObjArg instanceof FormDataObjIFace && oldDataObjArg instanceof FormDataObjIFace) { boolean hasSearch = mvParent != null && MultiView.isOptionOn(mvParent.getOptions(), MultiView.ADD_SEARCH_BTN); ((FormDataObjIFace) parentDataObjArg).removeReference((FormDataObjIFace) oldDataObjArg, cellNameArg, true); if (hasSearch && mvParent != null && ((FormDataObjIFace) oldDataObjArg).getId() != null) { mvParent.getTopLevel().addToBeSavedItem(oldDataObjArg); } } else { throw new RuntimeException("Hmmm, I don't think we soud be here."); } } } else { throw new RuntimeException("Hmmm,Why are we trying to delete a NULL object?"); } } /** * Walks the MultiView hierarchy and has them transfer their data from the UI to the DB Object * @param parentMV the parent MultiView */ public void traverseToGetDataFromForms() { traverseToGetDataFromForms(mvParent); } /** * Walks the MultiView hierarchy and has them transfer their data from the UI to the DB Object * @param parentMV the parent MultiView */ public static void traverseToGetDataFromForms(final MultiView parentMV) { for (MultiView mv : parentMV.getKids()) { mv.getDataFromUI(); traverseToGetDataFromForms(mv); } } /** * Sets the parent MultiView and all of its children. The last argument indicates whether * it should have the children walk there children (a deep recurse). * that the form is new * @param parentMV the parent MultiView * @param isNewForm whether the form is now in "new data input" mode * @param traverseKids whether the MultiView should traverse into the children MultiViews (deep recurse) */ protected void traverseToToSetAsNew(final MultiView parentMV, final boolean isNewForm, final boolean traverseKids) { // This call just sets all the Viewable for the MV, unless traverseKids is to true // then it walks the children MVs parentMV.setIsNewForm(isNewForm, traverseKids); // if traverseKids is true then the kids have already been walked // but if it is false then we need to walk the immediate kids if (!traverseKids) { for (MultiView mv : parentMV.getKids()) { mv.setIsNewForm(isNewForm, false); } } } /** * Sets the parent MultiView and all of its children. The last argument indicates whether * it should have the children walk there children (a deep recurse). * that the form is new * @param parentMV the parent MultiView * @param isNewForm whether the form is now in "new data input" mode * @param traverseKids whether the MultiView should traverse into the children MultiViews (deep recurse) */ protected void traverseToSetModified(final MultiView parentMV) { if (parentMV != null) { for (Viewable v : parentMV.getViewables()) { FormValidator fv = v.getValidator(); if (fv != null && fv.hasChanged()) { // They might be different because of a previous save or merge boolean doSetCreate = parentMV.getData() instanceof FormDataObjIFace && ((FormDataObjIFace) parentMV.getData()).getId() == null; FormHelper.updateLastEdittedInfo(parentMV.getData(), doSetCreate); if (parentMV.getData() != v.getDataObj()) { doSetCreate = v.getDataObj() instanceof FormDataObjIFace && ((FormDataObjIFace) v.getDataObj()).getId() == null; FormHelper.updateLastEdittedInfo(v.getDataObj(), doSetCreate); } } } // if traverseKids is true then the kids have already been walked for (MultiView mv : parentMV.getKids()) { traverseToSetModified(mv); } } } /** * @param parentMV */ protected void traverseToSaveControlData(final MultiView parentMV) { if (parentMV != null) { for (Viewable v : parentMV.getViewables()) { FormValidator fv = v.getValidator(); if (fv != null && fv.hasChanged() && v instanceof FormViewObj) { FormViewObj fvo = (FormViewObj) v; for (FormControlSaveable saveable : fvo.saveableList) { saveable.saveControlData(); } } } // if traverseKids is true then the kids have already been walked for (MultiView mv : parentMV.getKids()) { traverseToSaveControlData(mv); } } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#isDataCompleteAndValid(boolean) */ public boolean isDataCompleteAndValid(final boolean throwAwayOnDiscard) { //log.debug((formValidator != null) +" "+ formValidator.hasChanged() +" "+mvParent.isTopLevel() +" "+ mvParent.hasChanged()); // Figure out if it is New and whether it has changed or is incomplete boolean isNewAndComplete = true; if (mvParent != null) { Object topParentData = mvParent.getTopLevel().getData(); if (topParentData != null && topParentData instanceof FormDataObjIFace) { if (((FormDataObjIFace) topParentData).getId() == null) { if (formValidator != null && dataObj != null) { isNewAndComplete = formValidator.isFormValid(); } } } } //log.debug("Form Val: "+(formValidator != null && formValidator.hasChanged())); //log.debug("mvParent Val: "+(mvParent != null && mvParent.isTopLevel() && mvParent.hasChanged())); //if ((formValidator != null && formValidator.hasChanged()) || // (mvParent != null && mvParent.isTopLevel() && mvParent.hasChanged())) if (!doingDiscard && mvParent != null && mvParent.isTopLevel() && mvParent.hasChanged()) { try { doingDiscard = true; String title = null; if (dataObj != null) { if (tableInfo == null) { tableInfo = DBTableIdMgr.getInstance() .getByShortClassName(dataObj.getClass().getSimpleName()); } title = tableInfo != null ? tableInfo.getTitle() : null; if (StringUtils.isEmpty(title)) { title = UIHelper.makeNamePretty(dataObj.getClass().getSimpleName()); } } if (StringUtils.isEmpty(title)) { title = "data"; // I18N, not really sure what to put here. } // For the DISCARD // Since JOptionPane doesn't have a YES_CANCEL_OPTION // I have to use YES_NO_OPTION and since this is a Discard question // the rv has completely different meanings: // YES -> Means don't save (Discard) and close dialog (return true) // NO -> Means do nothing so return false String[] optionLabels; int dlgOptions; int defaultRV; if (!isNewAndComplete || (formValidator != null && !formValidator.isFormValid())) { dlgOptions = JOptionPane.YES_NO_OPTION; optionLabels = new String[] { getResourceString("DiscardChangesBtn"), getResourceString("CANCEL") }; defaultRV = JOptionPane.NO_OPTION; } else { dlgOptions = JOptionPane.YES_NO_CANCEL_OPTION; optionLabels = new String[] { getResourceString("SaveChangesBtn"), getResourceString("DiscardChangesBtn"), getResourceString("CANCEL") }; defaultRV = JOptionPane.CANCEL_OPTION; } int rv = JOptionPane.showOptionDialog(UIRegistry.getTopWindow(), isNewAndComplete ? UIRegistry.getLocalizedMessage("DiscardChanges", title) : UIRegistry.getLocalizedMessage("SaveChanges", title), isNewAndComplete ? getResourceString("DiscardChangesTitle") : getResourceString("SaveChangesTitle"), dlgOptions, JOptionPane.QUESTION_MESSAGE, null, optionLabels, optionLabels[0]); if (rv == JOptionPane.CLOSED_OPTION) { rv = defaultRV; } if (dlgOptions == JOptionPane.YES_NO_OPTION) { if (rv == JOptionPane.YES_OPTION) { discardCurrentObject(throwAwayOnDiscard); return true; } else if (rv == JOptionPane.NO_OPTION) { return false; } } else { if (rv == JOptionPane.YES_OPTION) { return saveObject(); } else if (rv == JOptionPane.CANCEL_OPTION) { return false; } else if (rv == JOptionPane.NO_OPTION) { // NO means Discard discardCurrentObject(throwAwayOnDiscard); return true; } } } finally { doingDiscard = false; } } else { return true; } return isNewAndComplete; } /** * Increments to the next number in the series. */ public void updateAutoNumbers() { if (isAutoNumberOn) { for (FVOFieldInfo fieldInfo : controlsById.values()) { Component comp = fieldInfo.getComp(); if (comp instanceof AutoNumberableIFace && comp.isEnabled()) { ((AutoNumberableIFace) comp).updateAutoNumbers(); } } } } /** * Returns whether a field with a given name or ID is auto-incremented. * @param fieldInfo the field info * @return true it is, false it isn't */ public boolean isFieldAutoNumbered(final FVOFieldInfo fieldInfo) { if (fieldInfo != null) { if (fieldInfo.getFormCell() instanceof FormCellFieldIFace) { FormCellFieldIFace fcf = (FormCellFieldIFace) fieldInfo.getFormCell(); UIFieldFormatterIFace uiff = UIFieldFormatterMgr.getInstance() .getFormatter(fcf.getUIFieldFormatterName()); if (uiff != null) { return uiff.getAutoNumber() != null; } } } return false; } /** * Asks the Business Rules if a SubViewIFace should have a new record created. */ public void initSubViews() { if (businessRules != null) { for (FVOFieldInfo fieldInfo : controlsById.values()) { if (fieldInfo.getFormCell() instanceof FormCellSubViewIFace && fieldInfo.getComp() instanceof MultiView && businessRules.shouldCreateSubViewData(fieldInfo.getName())) { MultiView mv = ((MultiView) fieldInfo.getComp()); FormViewObj fvo = mv.getCurrentViewAsFormViewObj(); if (fvo != null) { if (fvo.getRsController() != null && fvo.getRsController().getNewRecBtn() != null) { fvo.getRsController().getNewRecBtn().doClick(); } } } } } } /** * Returns whether a field with a given name is auto-incremented. * @param name the name of the field * @return true it is, false it isn't */ public boolean isFieldAutoNumberedByName(final String name) { return isFieldAutoNumbered(controlsByName.get(name)); } /** * Returns whether a field with a given ID is auto-incremented. * @param devName the ID of the field * @return true it is, false it isn't */ public boolean isFieldAutoNumberedById(final String id) { return isFieldAutoNumbered(controlsById.get(id)); } /** * Tells the Form it was cancelled when it was displayed from a SubViewBtn. */ public void doWasCacelled() { for (FVOFieldInfo fieldInfo : controlsById.values()) { //log.debug(fieldInfo.getFormCell().getType()+" "+fieldInfo.getComp()); if (fieldInfo.isOfType(FormCellIFace.CellType.subview) && fieldInfo.getComp() instanceof SubViewBtn) { ((SubViewBtn) fieldInfo.getComp()).wasCancelled(); } } } /** * Creates a new Record and adds it to the List and dataSet if necessary * @param doSetIntoAndValidateArg whether the new data object should be set into the form and validated. */ protected void createNewDataObject(final boolean doSetIntoAndValidateArg) { //log.debug("createNewDataObject " + this.getView().getName()); if (!isDataCompleteAndValid(false)) { return; } if (list != null && !list.isEmpty()) { getDataFromUI(); } doSetIntoAndValidate = doSetIntoAndValidateArg; // Check to see if the business rules will be creating the object // if so the BR will then call setNewObject if (businessRules != null && businessRules.canCreateNewDataObject()) { businessRules.createNewObj(true, null); } else { if (businessRules != null && mvParent != null) { if (mvParent.getMultiViewParent() != null && mvParent.getMultiViewParent().getData() != null) { if (!businessRules.isOkToAddSibling(mvParent.getMultiViewParent().getData())) { return; } } } // 06/16/09 - rods - no longer need to override the children objects. Let them be created anyway and then set overtop of them // this is because we don't know no in the business rules which ones should be created or not // from the CarryForward info //boolean shouldDoCarryForward = doCarryForward && carryFwdDataObj != null && carryFwdInfo != null; //log.info("createNewDataObject "+hashCode() + " Session ["+(session != null ? session.hashCode() : "null")+"] "); FormDataObjIFace obj; if (classToCreate != null) { obj = FormHelper.createAndNewDataObj(classToCreate, null, businessRules);//!shouldDoCarryForward); } else { obj = FormHelper.createAndNewDataObj(view.getClassName(), null, businessRules);//!shouldDoCarryForward); } // Fix for Bug 8898 - rods 08/20/2012 // the MultiView isn't getting the new Obj set into it when a new data object is created in the form viewable // here we just set it directly so nothing else gets called. if (mvParent != null && mvParent.data != null && mvParent.data.getClass() == obj.getClass()) { mvParent.data = obj; } setNewObject(obj); } } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.Viewable#setNewObject(edu.ku.brc.af.ui.forms.FormDataObjIFace) */ public void setNewObject(final FormDataObjIFace obj) { if (obj == null) { return; } oldDataObj = dataObj; dataObj = obj; UIValidator.setIgnoreAllValidation(this, true); for (FVOFieldInfo fieldInfo : controlsById.values()) { Component comp = fieldInfo.getComp(); if (comp != null && comp instanceof UIValidatable) { ((UIValidatable) comp).reset(); } } UIValidator.setIgnoreAllValidation(this, false); for (FVOFieldInfo fi : controlsByName.values()) { if (fi.getComp() instanceof EditViewCompSwitcherPanel) { ((EditViewCompSwitcherPanel) fi.getComp()).putIntoEditMode(); } } boolean shouldDoCarryForward = doCarryForward && carryFwdDataObj != null && carryFwdInfo != null; // The order needs to be set here because some Sets are TreSets which // require the ordinal to be set BEFORE it is added to the TreeSet if (obj instanceof Orderable) { // They really should all be Orderable, // but just in case we check each one. int maxOrder = -1; for (Object listObj : list) { if (listObj instanceof Orderable) { maxOrder = Math.max(((Orderable) listObj).getOrderIndex(), maxOrder); } } ((Orderable) obj).setOrderIndex(maxOrder + 1); } boolean isManyToOne = false; if (parentDataObj instanceof FormDataObjIFace) { boolean isASingleObj = false; DBTableInfo ti = DBTableIdMgr.getInstance().getByClassName(parentDataObj.getClass().getName()); if (ti != null) { DBRelationshipInfo ri = ti.getRelationshipByName(cellName); if (ri != null) { //log.debug(ri.getType()); if (ri.getType() == DBRelationshipInfo.RelationshipType.ManyToOne) { // not sure this is right anymore - rods 03/14/08 //isASingleObj = true; doSetIntoAndValidate = true; isManyToOne = true; } else if (ri.getType() == DBRelationshipInfo.RelationshipType.ZeroOrOne) { doSetIntoAndValidate = true; } } } if (isASingleObj) { obj.addReference(((FormDataObjIFace) parentDataObj), cellName); doSetIntoAndValidate = true; } else { ((FormDataObjIFace) parentDataObj).addReference(obj, cellName); } } else { FormHelper.addToParent(parentDataObj, obj); } boolean didCarryForward = false; if (shouldDoCarryForward) { // We don't need a Session when we are not cloning sets. //if (false) //{ // carryFwdInfo.carryForward(businessRules, carryFwdDataObj, obj); // //} else { DataProviderSessionIFace sessionLocal = null; try { sessionLocal = DataProviderFactory.getInstance().createSession(); sessionLocal.attach(carryFwdDataObj); carryFwdInfo.carryForward(businessRules, carryFwdDataObj, obj); didCarryForward = true; } catch (Exception ex) { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex); ex.printStackTrace(); } finally { if (sessionLocal != null) { sessionLocal.close(); } } } } if (businessRules != null) { businessRules.afterCreateNewObj(obj); } //if (businessRules != null) //{ //businessRules.addChildrenToNewDataObjects(obj); //} if (carryFwdDataObj == null && oldDataObj != null) { carryFwdDataObj = oldDataObj; } if (formValidator != null && formValidator.hasChanged()) { formValidator.setHasChanged(false); } dataObj = obj; isCreatingNewObject = true; if (list != null) { list.add(obj); int len = list.size(); if (rsController != null) { rsController.setLength(len); rsController.setIndex(len - 1, false); } } else if (mvParent.getMultiViewParent() != null) { // NOTE: This is primarily for single objects that are in a sub-form. // Not calling setHasNewData because we need to traverse and setHasNewData doesn't /////////////////////////////// // 02/03/09 rods - set second argument to false and that seems to fix several bugs // that was causing data to disappear because it was resetting the fields in the parent form. //traverseToToSetAsNew(mvParent.getMultiViewParent(), false, false); // don't traverse deeper than our immediate children indexChanged(-1); } isCreatingNewObject = false; if (recordSetItemList != null) { RecordSetItemIFace recordSetItem = recordSet.addItem(-1); recordSetItemList.add(recordSetItem); } isNewlyCreatedDataObj = true; if (rsController != null) { rsController.setNewObj(isNewlyCreatedDataObj); } if (formValidator != null) { formValidator.setNewObj(isNewlyCreatedDataObj); } notifyUIPluginsOfChanges(false, isNewlyCreatedDataObj); // Not calling setHasNewData because we need to traverse and setHasNewData doesn't traverseToToSetAsNew(mvParent, true, false); // don't traverse deeper than our immediate children updateControllerUI(); if (doSetIntoAndValidate) { if (list == null) // skip doing the setDataIntoUI because changing the index of will do it. { this.setDataIntoUI(); } if (formValidator != null) { formValidator.validateForm(); // OK, here we need to figure out if there are any required fields // that are empty. If there are than we need to tell the validator and the parent // validators that the forms are changed and are incomplete. boolean hasEmptyRequiredField = false; boolean hasRequiredFields = false; for (FVOFieldInfo fieldInfo : controlsById.values()) { if (fieldInfo.isOfType(FormCellIFace.CellType.field)) { Component comp = fieldInfo.getComp(); if (comp instanceof UIValidatable && comp instanceof GetSetValueIFace) { if (((UIValidatable) comp).isRequired()) { hasRequiredFields = true; if (((GetSetValueIFace) comp).getValue() == null) { hasEmptyRequiredField = true; } } } } } // OK, now tell all the validators up the chain that // things have changed and are incomplete. if (hasEmptyRequiredField) { formValidator.setFormValidationState(UIValidatable.ErrorType.Incomplete); formValidator.setHasChanged(true); formValidator.updateValidationBtnUIState(); if (mvParent != null) { MultiView mvp = mvParent; do { mvp.getCurrentValidator().setFormValidationState(UIValidatable.ErrorType.Incomplete); mvp.getCurrentValidator().setHasChanged(true); mvParent.getTopLevel().getCurrentViewAsFormViewObj().getValidator() .updateValidationBtnUIState(); mvp = mvp.getMultiViewParent(); } while (mvp != null); } mvParent.getTopLevel().getCurrentViewAsFormViewObj().getValidator() .updateValidationBtnUIState(); mvParent.getTopLevel().getCurrentValidator().updateSaveUIEnabledState(); } else if (hasRequiredFields) { formValidator.setFormValidationState(UIValidatable.ErrorType.Valid); formValidator.setHasChanged(true); formValidator.updateValidationBtnUIState(); } } } if (isManyToOne) { mvParent.setDataIntoParent(dataObj); } // Make the save button enabled if (didCarryForward && formValidator != null) { formValidator.setHasChanged(true); formValidator.updateSaveUIEnabledState(); formValidator.validateForm(); updateControllerUI(); } if (mvParent.isTopLevel()) { mvParent.initSubViews(); SwingUtilities.invokeLater(new Runnable() { public void run() { mvParent.focus(); } }); } else { focusFirstFormControl(); } if (selectorCBX != null) { selectorCBX.setEnabled(true); } // rods - 09/08/08 - this is to disable the MenuSwitcher when a new item is created if (switcherUI != null) { switcherUI.setEnabled(false); } } /** * The user tried to update or delete an object that was already changed by someone else. */ protected void recoverFromStaleObject(final String msgResStr, final String actualMsg) { JOptionPane.showMessageDialog(null, actualMsg != null ? actualMsg : getResourceString(msgResStr), getResourceString("Error"), JOptionPane.ERROR_MESSAGE); reloadDataObj(); } /** * Reloads a current (non-new) object from the database i nto the the form. */ protected void reloadDataObj() { if (!isNewlyCreatedDataObj) { if (mvParent != null) { mvParent.clearItemsToBeDeleted(); mvParent.clearItemsToBeSaved(); if (mvParent.isTopLevel()) { collectionViewState(); } } if (session != null && (mvParent == null || mvParent.isTopLevel())) { session.close(); } setSession(DataProviderFactory.getInstance().createSession()); //DataProviderFactory.getInstance().evict(dataObj.getClass()); if (list != null && dataObj instanceof FormDataObjIFace) { int index = list.indexOf(dataObj); Integer id = ((FormDataObjIFace) dataObj).getId(); if (id != null) { Class<?> cls = dataObj.getClass(); dataObj = session.get(cls, id); if (index > -1) { list.remove(index); list.insertElementAt(dataObj, index); } } else { // Bail out if the id is null meaning it is a new object return; } } else { dataObj = session.get(dataObj.getClass(), FormHelper.getId(dataObj)); } if (mvParent != null) { mvParent.setSession(session); mvParent.setData(dataObj); } else { setSession(session); this.setDataObj(dataObj); } this.setDataIntoUI(); if (viewStateList != null && viewStateList.size() > 0 && mvParent != null && mvParent.isTopLevel()) { if (mvParent != null) { mvParent.setViewState(viewStateList, altView.getMode(), 0); } viewStateList.clear(); } } } /** * */ protected void saveOnThread(final boolean saveAndNewArg) { //if (true) { if (saveObject() && saveAndNewArg) { createNewDataObject(true); } } /* else { UIRegistry.writeSimpleGlassPaneMsg("Saving...", 20); // I18N saveControl.setEnabled(false); javax.swing.SwingWorker<Integer, Integer> bldWorker = new javax.swing.SwingWorker<Integer, Integer>() { @Override protected Integer doInBackground() throws Exception { if (saveObject() && saveAndNewArg) { createNewDataObject(true); } return null; } @Override protected void done() { super.done(); UIRegistry.clearSimpleGlassPaneMsg(); //saveControl.setEnabled(true); } }; bldWorker.execute(); }*/ } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#doSave() */ public boolean doSave() { return saveObject(); } /** * @param mv * @return */ private BusinessRulesIFace recurseProcessBR(final MultiView mv) { BusinessRulesIFace busRulesRV = null; FormViewObj fvo = mv.getCurrentViewAsFormViewObj(); if (fvo != null && fvo.getAltView().getMode() == AltViewIFace.CreationMode.EDIT) { Object fvoDataObj = fvo.getCurrentDataObj(); BusinessRulesIFace busRules = fvo.getBusinessRules(); if (busRules != null && fvoDataObj != null) { BusinessRulesIFace.STATUS status = busRules.processBusinessRules(fvoDataObj); if (status != BusinessRulesIFace.STATUS.OK && status != BusinessRulesIFace.STATUS.None) { busRulesRV = busRules; } } } for (MultiView childMV : mv.getKids()) { BusinessRulesIFace brInError = recurseProcessBR(childMV); if (brInError != null) { return brInError; } } return busRulesRV; } /** * This helper method deletes each item from the list after checking the busniess rules * @param localSession a session to use to delete * @param deletedItems the list of data objects * @throws Exception */ public static void deleteItemsInDelList(final DataProviderSessionIFace localSession, final Vector<Object> deletedItems) throws Exception { for (Object obj : deletedItems) { if (!(obj instanceof DataModelObjBase) || ((DataModelObjBase) obj).getId() != null) { BusinessRulesIFace delBusRules = DBTableIdMgr.getInstance().getBusinessRule(obj); // notify the business rules object that a deletion is going to happen Object obj2 = localSession.merge(obj); if (delBusRules != null) { obj2 = delBusRules.beforeDelete(obj2, localSession); } localSession.delete(obj2); } } for (Object obj : deletedItems) { if (!(obj instanceof DataModelObjBase) || ((DataModelObjBase) obj).getId() != null) { BusinessRulesIFace delBusRules = DBTableIdMgr.getInstance().getBusinessRule(obj); // notify the business rules object that a deletion is going to be committed if (delBusRules != null) { if (!delBusRules.beforeDeleteCommit(obj, localSession)) { throw new Exception("Business rules processing failed"); } } } } } /** * This helper method is used to update/save those items that have been removed from a relationship * @param localSession a session to use to delete * @param toBeSavedItems the list of data objects * @throws Exception */ public static void saveItemsInToBeSavedList(final DataProviderSessionIFace localSession, final Vector<Object> toBeSavedItems) throws Exception { for (Object obj : toBeSavedItems) { obj = localSession.merge(obj); localSession.saveOrUpdate(obj); } } /** * This method enables us to loop when there is a duplicate key * @param dataObj the data object to be saved * @return the merged object, or null if there was an error. */ protected SAVE_STATE saveToDB(final Object dataObjArg) { if (dataObjArg == null) { if (saveControl != null) { saveControl.setEnabled(false); } return SAVE_STATE.SaveOK; } SAVE_STATE saveState = SAVE_STATE.Initial; boolean isDuplicateError = false; boolean tryAgain = false; int numTries = 0; Vector<Object> deletedItems = mvParent != null ? mvParent.getDeletedItems() : null; Vector<Object> toBeSavedItems = mvParent != null ? mvParent.getToBeSavedItems() : null; Object dObj = null; do { try { numTries++; Integer dataObjId = ((FormDataObjIFace) dataObjArg).getId(); if (dataObjId != null) { DataProviderSessionIFace session1 = DataProviderFactory.getInstance().createSession(); Integer count = null; try { count = session1.getDataCount(dataObjArg.getClass(), "id", dataObjId, DataProviderSessionIFace.CompareType.Equals); } catch (Exception ex) { ex.printStackTrace(); } finally { if (session1 != null) session1.close(); } if (count == null || count == 0) { UIRegistry.showLocalizedError("FormViewObj.DATA_OBJ_MISSING"); setHasNewData(false); removeObject(true); return SAVE_STATE.Error; } } // First get data so business Rules can be checked this.getDataFromUI(); traverseToGetDataFromForms(mvParent); //log.debug("saveObject checking businessrules for [" + (dataObjArg != null ? dataObjArg.getClass(): "null") + "]"); //if (businessRules != null && businessRules.processBusinessRules(dataObjArg) == BusinessRulesIFace.STATUS.Error) BusinessRulesIFace busRuleInError = recurseProcessBR(mvParent); if (busRuleInError != null) { UIRegistry.showError(busRuleInError.getMessagesAsString()); return null; } // Now update the auto number fields and re-get all the data // we can't update the auto number fields before we run the business rules. mvParent.updateAutoNumbers(); this.getDataFromUI(); traverseToGetDataFromForms(mvParent); // XXX FINAL RELEASE - Need to walk the form tree and set them manually //FormHelper.updateLastEdittedInfo(dataObjArg); traverseToSetModified(getMVParent()); session.beginTransaction(); if (numTries == 1 && deletedItems != null && deletedItems.size() > 0) { //As far as I can tell it is not necessary to delete the items by hand, hibernate will delete them automatically //when the parent object is saved. EXCEPT if constraint violations are present due to user actions: //Say a user deletes Jim Jones from the collector list, and then changes mind and adds Jim Jones, and saves. //Then it is necessary to delete here -- I think because hibernate doesn't work. //If not for the merging done by business rules for embedded collectingevents it would be possible //to only delete manually if numTries was 2, i.e. hibernate failed the first try, but the merging generates //exceptions for duplicate keys that are not thrown up to this method but mess up the session. deleteItemsInDelList(session, deletedItems); try { //need to flush so later actions in the transaction know about the deletes. session.flush(); } catch (org.hibernate.ObjectDeletedException odex) { //for some reason, for authors (apparently ONLY authors, even though the annotations look the same as for collector, groupmember), //hibernate will complain that the object "will be re-saved by cascade rules". If we just ignore the exception hibernate cascade deletes the object later. log.warn(odex.getMessage()); } } if (numTries == 1 && toBeSavedItems != null) { //see remarks above for deletes. //No problems here so far, so just do it the first time around. saveItemsInToBeSavedList(session, toBeSavedItems); } if (businessRules != null) { businessRules.startProcessingBeforeAfterRules(); businessRules.beforeMerge(dataObjArg, session); } dObj = session.merge(dataObjArg); if (businessRules != null) { businessRules.beforeSave(dObj, session); } session.saveOrUpdate(dObj); if (businessRules != null) { if (!businessRules.beforeSaveCommit(dObj, session)) { throw new Exception("Business rules processing failed"); } } session.commit(); session.flush(); if (mvParent != null) { mvParent.clearItemsToBeSaved(); } if (deletedItems != null) { // notify the business rules object that a deletion has occurred for (Object obj : deletedItems) { BusinessRulesIFace delBusRules = DBTableIdMgr.getInstance().getBusinessRule(obj); if (delBusRules != null) { delBusRules.afterDeleteCommit(obj); } } deletedItems.clear(); } tryAgain = false; isNewlyCreatedDataObj = isCreatingNewObject; // shouldn't be needed, but just in case if (rsController != null) { rsController.setNewObj(isNewlyCreatedDataObj); } if (formValidator != null) { formValidator.setNewObj(isNewlyCreatedDataObj); } saveState = SAVE_STATE.SaveOK; dataObj = dObj; for (FVOFieldInfo fi : controlsByName.values()) { if (fi.getComp() instanceof EditViewCompSwitcherPanel) { ((EditViewCompSwitcherPanel) fi.getComp()).putIntoViewMode(); } } } catch (StaleObjectException e) // was StaleObjectStateException { session.rollback(); recoverFromStaleObject("UPDATE_DATA_STALE", null); tryAgain = false; dObj = dataObj; saveState = SAVE_STATE.StaleRecovery; //e.printStackTrace(); } catch (ConstraintViolationException e) { //edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); //edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, e); log.error(e); log.error(e.getSQLException()); log.error(e.getSQLException().getSQLState()); // This check here works for MySQL in English "Duplicate entry" // we can add other Databases as we go // The idea of this code is that if we are certain it failed on a constraint because // of a duplicate key error then we will try a couple of more times. // // The number 5 and 3 below are completely arbitrary, I just choose them // because they seemed right. // String errMsg = e.getSQLException().toString(); if (StringUtils.isNotEmpty(errMsg) && errMsg.indexOf("Duplicate entry") > -1) { isDuplicateError = true; } tryAgain = (isDuplicateError && numTries < 5) || (!isDuplicateError && numTries < 3); isDuplicateError = false; // Ok, we tried a couple of times and have decided to give up. if (!tryAgain) { session.rollback(); recoverFromStaleObject("DUPLICATE_KEY_ERROR", null); dObj = dataObj; saveState = SAVE_STATE.StaleRecovery; } } catch (org.hibernate.ObjectNotFoundException ex) { //edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); //edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex); String errMsg = null; String msg = ex.toString(); if (StringUtils.contains(msg, "No row with the given identifier exists")) { int sInx = msg.indexOf('['); int eInx = msg.lastIndexOf(']'); if (sInx > -1 && eInx > -1) { msg = msg.substring(sInx + 1, eInx); eInx = msg.lastIndexOf('#'); if (eInx > -1) { msg = msg.substring(0, eInx); DBTableInfo ti = DBTableIdMgr.getInstance().getByClassName(msg); if (ti != null) { errMsg = String.format(getResourceString("FormViewObj.FIELD_STALE_TITLE"), ti.getTitle()); } } } } if (errMsg == null) { errMsg = getResourceString("FormViewObj.FIELD_STALE"); } session.rollback(); recoverFromStaleObject("UNRECOVERABLE_DB_ERROR", errMsg); saveState = SAVE_STATE.StaleRecovery; } catch (Exception e) { session.rollback(); // This happens when MySQL doesn't have permissions // to INSERT, UPDATE, OR DELETE if (e instanceof SQLGrammarException) { String msg = e.getCause().getMessage(); if (StringUtils.contains(msg.toLowerCase(), "denied")) { UIRegistry.showLocalizedError("FormViewObj.MISSING_DB_PERMS"); } } else { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, e); log.error("******* " + e); e.printStackTrace(); } recoverFromStaleObject("UNRECOVERABLE_DB_ERROR", null); saveState = SAVE_STATE.StaleRecovery; } } while (tryAgain); return saveState; } /** * */ public Vector<ViewState> collectionViewState() { if (viewStateList == null) { viewStateList = new Vector<ViewState>(); } viewStateList.clear(); if (mvParent != null) { mvParent.collectionViewState(viewStateList, altView.getMode(), 2); } return viewStateList; } /** * Save any changes to the current object */ public boolean saveObject() { if (mvParent != null && mvParent.isTopLevel()) { collectionViewState(); } if (session != null && (mvParent == null || mvParent.isTopLevel())) { session.close(); } setSession(DataProviderFactory.getInstance().createSession()); //log.info("saveObject "+hashCode() + " Session ["+(session != null ? session.hashCode() : "null")+"]"); if (businessRules != null) { if (!businessRules.isOkToSave(dataObj, session)) { UIRegistry.showLocalizedError(businessRules.getMessagesAsString()); return false; } } Object beforeSaveDataObj = dataObj; SAVE_STATE saveState = saveToDB(dataObj); if (saveState == SAVE_STATE.SaveOK) { if (businessRules != null) { businessRules.afterSaveCommit(dataObj, session); } try { traverseToSaveControlData(mvParent); } catch (Exception ex) { ex.printStackTrace(); } session.refresh(dataObj); replaceDataObjInList(beforeSaveDataObj, dataObj); if (origDataSet != null) { origDataSet.remove(beforeSaveDataObj); origDataSet.add(dataObj); } log.info("Session Saved[ and Flushed " + session.hashCode() + "]"); CommandDispatcher.dispatch(new CommandAction("Data_Entry", "SaveBeforeSetData", dataObj)); setDataIntoUI(); if (formValidator != null) { formValidator.setHasChanged(false); } if (mvParent != null) { mvParent.clearValidators(); if (mvParent.isTopLevel() && beforeSaveDataObj == mvParent.getData()) { mvParent.setJustDataObj(dataObj); } } // Not calling setHasNewData because we need to traverse and setHasNewData doesn't traverseToToSetAsNew(mvParent, false, true); // last arg means it should traverse updateControllerUI(); //if (doCarryForward) //{ carryFwdDataObj = dataObj; //} if (saveControl != null) { saveControl.setEnabled(false); } if (selectorCBX != null) { selectorCBX.setEnabled(false); } if (session != null && (mvParent == null || mvParent.isTopLevel())) { session.close(); setSession(null); } if (viewStateList != null && viewStateList.size() > 0 && mvParent != null && mvParent.isTopLevel()) { if (mvParent != null) { mvParent.setViewState(viewStateList, altView.getMode(), 0); } viewStateList.clear(); } CommandDispatcher.dispatch(new CommandAction("Data_Entry", "Save", dataObj)); //log.debug("After save"); //log.debug("Form Val: "+(formValidator != null && formValidator.hasChanged())); //log.debug("mvParent Val: "+(mvParent != null && mvParent.isTopLevel() && mvParent.hasChanged())); if (businessRules != null) { businessRules.saveFinalization(dataObj); } return true; } if (businessRules != null) { businessRules.afterSaveFailure(dataObj, session); } return false; } /** * @param oldDO * @param newDO */ protected void replaceDataObjInList(final Object oldDO, final Object newDO) { //if (oldDO != null && newDO != null) //{ // log.debug("Replacing "+oldDO.getClass().getSimpleName()+" "+oldDO.hashCode()+" with "+newDO.getClass().getSimpleName()+" "+newDO.hashCode()); //} if (list != null) { int index = list.indexOf(oldDO); if (index > -1) { list.remove(oldDO); if (oldDO != null) { log.error( "Removed " + oldDO.getClass().getSimpleName() + " " + oldDO.hashCode() + " from list."); } list.insertElementAt(newDO, index); log.error("list length: " + list.size() + " inx: " + index); } else { if (oldDO != null) { log.error("************ " + oldDO.getClass().getSimpleName() + " " + oldDO.hashCode() + " couldn't be found in list."); } } } } /** * This adjusts the rsController after an item has been deleted, it gets a new item * to fill the form if on exists. */ protected void adjustRSControllerAfterRemove() { if (rsController != null) { int currInx = rsController.getCurrentIndex(); int newLen = rsController.getLength() - 1; int newInx = Math.min(currInx, newLen - 1); if (list != null) { list.remove(currInx); // remove from list } if (recordSetItemList != null) { recordSetItemList.remove(currInx); // remove from list } rsController.setLength(newLen); // set new len for controller if (newInx > -1 && (list == null || list.size() > 0)) { isEditing = false; rsController.setIndex(newInx, mvParent == null); // only send notification about index change top form isEditing = true; // rods - 07/07/2008 - This has already been at this point when the index changed. // and this ends //dataObj = list.get(newInx); //setDataObj(dataObj, true); // true means the dataObj is already in the current "list" of data items we are working with if (formValidator != null) { formValidator.validateForm(); } } else { setDataObj(null, true); // true means the dataObj is already in the current "list" of data items we are working with } updateControllerUI(); if (newLen == 0 && formValidator != null) { formValidator.setHasChanged(false); formValidator.setFormValidationState(UIValidatable.ErrorType.Valid); formValidator.updateValidationBtnUIState(); // requires manual overridew becase the validator is disabled. } } else if (MultiView.isOptionOn(options, MultiView.IS_SINGLE_OBJ)) { setDataObj(null, false); // true means the dataObj is already in the current "list" of data items we are working with } } /** * Save any changes to the current object */ protected void askToRemoveObject() { boolean addSearch = mvParent != null && MultiView.isOptionOn(mvParent.getOptions(), MultiView.ADD_SEARCH_BTN); Object[] delBtnLabels = { getResourceString(addSearch ? "Remove" : "Delete"), getResourceString("CANCEL") }; String title = dataObj instanceof FormDataObjIFace ? ((FormDataObjIFace) dataObj).getIdentityTitle() : tableInfo.getTitle(); int rv = JOptionPane.showOptionDialog(UIRegistry.getTopWindow(), UIRegistry.getLocalizedMessage(addSearch ? "ASK_REMOVE" : "ASK_DELETE", title), getResourceString(addSearch ? "Remove" : "Delete"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, delBtnLabels, delBtnLabels[1]); if (rv != JOptionPane.YES_OPTION) { return; } // We do this because the process of determining whether something can be deleted might take a while. if (addSearch) { doDeleteDataObj(dataObj, session, true); } else if (businessRules != null) { UIRegistry.getStatusBar().setIndeterminate(STATUSBAR_NAME, true); final SwingWorker worker = new SwingWorker() { public Object construct() { businessRules.okToDelete(dataObj, session, FormViewObj.this); return null; } //Runs on the event-dispatching thread. public void finished() { UIRegistry.getStatusBar().setProgressDone(STATUSBAR_NAME); if (session != null) { session.close(); } } }; worker.start(); } else // No Business Rules { doDeleteDataObj(dataObj, session, true); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.BusinessRulesOkDeleteIFace#doDeleteDataObj(java.lang.Object, edu.ku.brc.dbsupport.DataProviderSessionIFace, boolean) */ public void doDeleteDataObj(final Object dataObjArg, final DataProviderSessionIFace sessionArg, final boolean doDelete) { if (doDelete) { removeObject(false); } else { DBTableInfo ti = DBTableIdMgr.getInstance().getByClassName(dataObjArg.getClass().getName()); StringBuilder sb = new StringBuilder(); sb.append(String.format(getResourceString("COULDNT_DELETE_OBJ"), ti.getTitle(), ((FormDataObjIFace) dataObjArg).getIdentityTitle())); sb.append("\n"); sb.append(getResourceString("BR_FOUNDINTABLE_LABEL")); sb.append("\n"); for (String s : businessRules.getWarningsAndErrors()) { sb.append(" "); sb.append(s); sb.append("\n"); } JOptionPane.showMessageDialog(UIRegistry.getTopWindow(), sb.toString(), getResourceString("COULDNT_DELETE_OBJ_TITLE"), JOptionPane.WARNING_MESSAGE); } } /** * Save any changes to the current object */ protected void removeObject(final boolean doSkipAlreadyDelMsg) { // This shouldn't happen if (session != null) { session.close(); } setSession(DataProviderFactory.getInstance().createSession()); try { //log.info(hashCode() + " Session ["+(session != null ? session.hashCode() : "null")+"] "); if (session == null) { return; } // rods - 08/21/08 Needed to add this so could remove the other side of the relationship // which might have failed from being lazy loaded. //session.attach(parentDataObj); // 09/23/08 - Bug 5996 When the dataObj fails to attach it is most likely // because it has been changed. Which we don't care about because we are deleting it //boolean attachFailed = false; if (((FormDataObjIFace) dataObj).getId() != null) { try { session.attach(dataObj); if (carryFwdDataObj != null && carryFwdDataObj instanceof FormDataObjIFace) { FormDataObjIFace fdo = (FormDataObjIFace) carryFwdDataObj; if (fdo.getId() != null && fdo.getId().equals(((FormDataObjIFace) dataObj).getId())) { boolean doClear = true; if (list != null && rsController != null) { int inx = rsController.getCurrentIndex(); if (inx > -1 && inx < list.size()) { carryFwdDataObj = list.get(Math.max(0, inx - 1)); doClear = false; } } if (doClear) { carryFwdDataObj = null; } if (carryFwdDataObj == null && isCarryForwardConfgured()) { UIRegistry.showLocalizedMsg("FormViewObj.NO_CF_OBJ"); } } } } catch (org.hibernate.HibernateException ex) { // we could check the type to make sure it was a "dirty colleciton" error // but for now I am not. //attachFailed = true; } } removeFromParent(mvParent, parentDataObj, cellName, dataObj); // Delete a child object by caching it in the Top Level MultiView if (mvParent != null && !mvParent.isTopLevel()) { boolean addSearch = mvParent != null && MultiView.isOptionOn(mvParent.getOptions(), MultiView.ADD_SEARCH_BTN); // We don't delete these type of objects from the database // because were added as references only if (!addSearch) { mvParent.getTopLevel().addDeletedItem(dataObj); } String delMsg = (businessRules != null) ? businessRules.getDeleteMsg(dataObj) : ""; UIRegistry.getStatusBar().setText(delMsg); formValidator.setHasChanged(true); formValidator.validateForm(); // We need to turn off the notifications when setting new data. formValidator.setIgnoreValidationNotifications(true); adjustRSControllerAfterRemove(); formValidator.setIgnoreValidationNotifications(false); mvParent.getTopLevel().getCurrentValidator().setHasChanged(true); mvParent.getTopLevel().getCurrentValidator().validateForm(); isNewlyCreatedDataObj = false; // shouldn't be needed, but just in case if (rsController != null) { rsController.setNewObj(isNewlyCreatedDataObj); } if (formValidator != null) { formValidator.setNewObj(isNewlyCreatedDataObj); } if (session != null) { session.close(); setSession(null); } return; } String delMsg = (businessRules != null) ? businessRules.getDeleteMsg(dataObj) : ""; boolean doClearObj = true; try { // Clear the items in the "deleted" cache because they will be deleted anyway. if (mvParent != null) { mvParent.clearItemsToBeDeleted(); } FormDataObjIFace fdo = (FormDataObjIFace) dataObj; Integer objId = fdo.getId(); if (objId != null) { // 11/5/2010 rods - Always close session because the evict below doesn't work //if (attachFailed) { session.close(); setSession(DataProviderFactory.getInstance().createSession()); } //session.evict(dataObj); // Reload the object from the database to avoid a stale object exception. Object dbDataObj = session.getData(fdo.getDataClass(), "id", objId, DataProviderSessionIFace.CompareType.Equals); if (dbDataObj != null) { session.beginTransaction(); if (businessRules != null) { //dbDataObj = businessRules.beforeDelete(dbDataObj, session); } session.delete(dbDataObj); if (businessRules != null) { if (!businessRules.beforeDeleteCommit(dbDataObj, session)) { session.rollback(); throw new Exception("Business rules processing failed"); } } session.commit(); session.flush(); if (businessRules != null) { businessRules.afterDeleteCommit(dbDataObj); } if (mvParent.isTopLevel() && mvParent.getCurrentValidator() != null) { mvParent.getCurrentValidator().setUIValidatorsToNotChanged(); } } else { doClearObj = true; if (!doSkipAlreadyDelMsg) { UIRegistry.showLocalizedMsg("OBJ_ALREADY_DEL"); } } updateAfterRemove(false); } } catch (edu.ku.brc.dbsupport.StaleObjectException e) { e.printStackTrace(); doClearObj = false; session.rollback(); recoverFromStaleObject("DELETE_DATA_STALE", null); } catch (Exception e) { e.printStackTrace(); doClearObj = false; session.rollback(); recoverFromStaleObject("DELETE_DATA_STALE", null); } log.debug("Session Flushed[" + (session != null ? session.hashCode() : "no session") + "]"); if (doClearObj) { adjustRSControllerAfterRemove(); UIRegistry.getStatusBar().setText(delMsg); } else { UIRegistry.getStatusBar().setText(getResourceString("OBJ_NOT_DELETED")); } } catch (Exception e) { e.printStackTrace(); edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, e); log.error("******* " + e); } finally { if (session != null && (mvParent == null || mvParent.isTopLevel())) { session.close(); setSession(null); } } if (saveControl != null && list != null && list.size() == 0) { saveControl.setEnabled(false); } } /** * Sets the "newly created object" in the controller and the validator to false * and closes and frames that are showing. * @param doAdjustRS true calls adjustRSControllerAfterRemove and removes the item from the list */ public void updateAfterRemove(final boolean doAdjustRS) { isNewlyCreatedDataObj = false; // shouldn't be needed, but just in case if (rsController != null) { rsController.setNewObj(isNewlyCreatedDataObj); } if (formValidator != null) { formValidator.setNewObj(isNewlyCreatedDataObj); } if (mvParent != null) { mvParent.shutdownDisplayFrames(); } if (doAdjustRS) { // Nees to be put out on GUI thread to prevent lock up SwingUtilities.invokeLater(new Runnable() { /* (non-Javadoc) * @see java.lang.Runnable#run() */ @Override public void run() { adjustRSControllerAfterRemove(); } }); } } /** * Tells this form and all of it's children that it is a "new" form for data entry. * @param isNewForm true is new, false is not */ public void setHasNewData(final boolean isNewForm) { isNewlyCreatedDataObj = isNewForm; // rods - 09/05/08 - added so "+" can be disabled for new forms with data updateControllerUI(); } /** * Returns the list of MultiView kids (subforms). * @return the list of MultiView kids (subforms) */ public List<MultiView> getKids() { return kids; } /** * Debug method - lists the fields that have changed. */ public void listFieldChanges() { try { if (formValidator != null) { log.debug("=================================== " + formValidator.getDCNs().values().size()); for (DataChangeNotifier dcn : formValidator.getDCNs().values()) { FVOFieldInfo fieldInfo = controlsById.get(dcn.getId()); if (fieldInfo != null) { log.debug("Changed Field[" + fieldInfo.getName() + "]\t[" + (dcn.isDataChanged() ? "CHANGED" : "not changed") + "]"); } else { log.debug("Field Info is null for dcn.getId()[" + dcn.getId() + "]"); } } log.debug("==================================="); } } catch (Exception ex) { log.error(ex); } } /** * This will choose the first focusable UI component that doesn't have a value. * BUT! It always chooses a JTextField over anything else. * (NOTE: We may want a non-JTextField that is required to override a JTextField that is not.) * * @return the focusable first object. */ public Component getFirstFocusable() { int insertPos = Integer.MAX_VALUE; Component focusable = null; Component first = null; for (FVOFieldInfo compFI : compsList) { Component comp = compFI.getComp(); if (comp.isEnabled() && comp.isFocusable() && comp instanceof GetSetValueIFace) { Object val = ((GetSetValueIFace) comp).getValue(); if (val == null || (val instanceof String && StringUtils.isEmpty((String) val))) { if (comp instanceof ValFormattedTextFieldSingle) { ValFormattedTextFieldSingle vtf = (ValFormattedTextFieldSingle) comp; if (vtf.getFormatter() != null && vtf.getFormatter().isIncrementer()) { continue; } } boolean override = false;//focusable instanceof JTextField && !(comp instanceof JTextField); if (compFI.getInsertPos() < insertPos || override) { if (comp instanceof UIValidatable) { focusable = ((UIValidatable) comp).getValidatableUIComp(); } else { focusable = comp; } if (!override) // keep the same (lower) position as the original { insertPos = compFI.getInsertPos(); } } } if (compFI.getInsertPos() == 0) { first = comp; } } } if (focusable instanceof JTextField && !(first instanceof JTextField)) { return focusable; } return first != null ? first : focusable; } /** * Sets the focus to the first control in the form. */ public void focusFirstFormControl() { Component focusable = getFirstFocusable(); if (focusable != null) { focusable.requestFocus(); } } /** * This method is called by the add button to create a new object in the form. */ public void createNewObjectByAdding() { UIValidator.setIgnoreAllValidation(this, true); createNewDataObject(false); if (formValidator != null) { formValidator.processFormRules(); // 4/6/09 rods - Bug 6886 The first and prev btns were getting enabled and shouldn't been. if (rsController != null) { rsController.setUIEnabled(false); if (rsController.getRecDisp() != null) { rsController.getRecDisp().setEnabled(true); } } } UIValidator.setIgnoreAllValidation(this, false); //focusFirstFormControl(); } /** * Adds the the ActionListener to the btns. */ protected void setAddDelListeners(final JButton addBtn, final JButton delBtn) { if (addBtn != null) { addBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { createNewObjectByAdding(); } }); } if (delBtn != null) { delBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { askToRemoveObject(); } }); } } /** * Adds the ResultSetController to the panel. * @param addSearch indicates it should add a search btn */ protected void addRSController(final boolean addSearch) { // If the Control panel doesn't exist, then add it if (rsController == null && controlPanel != null) { boolean canAdd = true; boolean canDel = true; if (AppContextMgr.isSecurityOn()) { if (perm == null) { if (tableInfo != null) { perm = tableInfo.getPermissions(); } else { perm = MultiView.getPremissionFromView(view, MultiView.getClassNameFromParentMV(dataClass, mvParent, cellName)); } //SecurityMgr.dumpPermissions(mvParentArg.getViewName(), perm.getOptions()); canAdd = perm.canAdd(); canDel = perm.canDelete(); } } boolean mvHasSeparator = mvParent.getSeparator() != null; boolean inEditMode = altView.getMode() == AltViewIFace.CreationMode.EDIT; rsController = new ResultSetController(formValidator, inEditMode && !addSearch && canAdd, // Add New inEditMode && canDel, // Add Delete inEditMode && addSearch && canAdd, // Add Search view.getObjTitle(), // Object Title 0, // current length !mvHasSeparator); // don't layout the btns rsController.getPanel().setBackground(bgColor); if (mvParent.isTopLevel()) { rsController.setupGotoListener(); } rsController.addListener(this); controlPanel.addController(rsController.getPanel()); controlPanel.setRecordSetController(rsController); newRecBtn = rsController.getNewRecBtn(); delRecBtn = rsController.getDelRecBtn(); if (addSearch) { if (delRecBtn != null) { String removeTTStr = ResultSetController.createTooltip("RemoveRecordTT", view.getObjTitle()); delRecBtn.setIcon(IconManager.getIcon("Eraser16", IconManager.IconSize.Std16)); delRecBtn.setToolTipText(removeTTStr); } JButton searchButton = rsController.getSearchRecBtn(); if (searchButton != null) { searchButton.setIcon(IconManager.getIcon("SearchAdd", IconManager.IconSize.Std16)); String saTTStr = ResultSetController.createTooltip("SearchAddRecordTT", view.getObjTitle()); searchButton.setToolTipText(saTTStr); } } if (formValidator != null && newRecBtn != null) { formValidator.addEnableItem(newRecBtn, FormValidator.EnableType.ValidItems); } setAddDelListeners(newRecBtn, delRecBtn); if (mvHasSeparator) { addControllerBtnsToSep(); } } } /** * Adds all the Control buttons to the separator. */ protected void addControllerBtnsToSep() { JButton searchBtn = rsController.getSearchRecBtn(); int cnt = (newRecBtn != null ? 1 : 0) + (delRecBtn != null ? 1 : 0) + (searchBtn != null ? 1 : 0); PanelBuilder pb = new PanelBuilder( new FormLayout(UIHelper.createDuplicateJGoodiesDef("p", "2px", cnt), "p")); int x = 1; if (newRecBtn != null) { pb.add(newRecBtn, cc.xy(x, 1)); x += 2; } if (delRecBtn != null) { pb.add(delRecBtn, cc.xy(x, 1)); x += 2; } if (searchBtn != null) { pb.add(searchBtn, cc.xy(x, 1)); x += 2; } pb.getPanel().setOpaque(false); sepController = pb.getPanel(); } /** * Creates the extra btns. */ protected void createAddDelSearchPanel() { if (controlPanel != null && formValidator != null) { boolean doAddSearch = mvParent != null && MultiView.isOptionOn(mvParent.getOptions(), MultiView.ADD_SEARCH_BTN); Insets insets = new Insets(1, 1, 1, 1); PanelBuilder rowBuilder = new PanelBuilder( new FormLayout("f:p:g,p,2px,p" + (doAddSearch ? ",2px,p" : ""), "p")); /*newRecBtn = new JButton("+") { public void setEnabled(boolean enable) { System.err.println("> "+enable); super.setEnabled(enable); } };*/ newRecBtn = UIHelper.createIconBtn("NewRecord", null, null); newRecBtn.setToolTipText(ResultSetController.createTooltip("NewRecordTT", view.getObjTitle())); newRecBtn.setMargin(insets); rowBuilder.add(newRecBtn, cc.xy(2, 1)); delRecBtn = UIHelper.createIconBtn("DeleteRecord", null, null); delRecBtn.setToolTipText(ResultSetController.createTooltip("DeleteRecordTT", view.getObjTitle())); delRecBtn.setMargin(insets); rowBuilder.add(delRecBtn, cc.xy(4, 1)); if (doAddSearch) { srchRecBtn = UIHelper.createIconBtn("SearchAdd", IconManager.IconSize.Std16, null, null); srchRecBtn .setToolTipText(ResultSetController.createTooltip("SearchForRecordTT", view.getObjTitle())); srchRecBtn.setMargin(insets); srchRecBtn.setOpaque(false); rowBuilder.add(srchRecBtn, cc.xy(6, 1)); DBTableInfo tblInfo = DBTableIdMgr.getInstance().getByClassName(view.getClassName()); if (tblInfo != null) { searchName = tblInfo.getSearchDialog(); if (StringUtils.isEmpty(searchName)) { searchName = ""; // Note not null but empty tells it to disable the search btn } } srchRecBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { doSearch(); } }); } rowBuilder.getPanel().setOpaque(false); newRecBtn.setOpaque(false); delRecBtn.setOpaque(false); // This is the Old way //controlPanel.addController(rowBuilder.getPanel()); // This is the new way sepController = rowBuilder.getPanel(); // 2/13/09 - rods - The last two checks determine if it is a 'Single' item if (formValidator != null && newRecBtn != null && rsController != null && origDataSet != null) { formValidator.addEnableItem(newRecBtn, FormValidator.EnableType.ValidItems); } setAddDelListeners(newRecBtn, delRecBtn); } } /** * */ protected void doSearch() { if (StringUtils.isNotEmpty(searchName)) { ViewBasedSearchDialogIFace dlg = UIRegistry.getViewbasedFactory() .createSearchDialog(UIHelper.getWindow(mainComp), searchName); dlg.setMultipleSelection(true); dlg.getDialog().setModal(true); dlg.getDialog().setVisible(true); if (!dlg.isCancelled()) { // Some object that are searched for need to have a new parent // so we ask them if they want us to create one for them // and then we hand it to them. // Otherwise we just set the new object into the form. List<Object> newDataObjects = dlg.getSelectedObjects(); boolean doSetNewDataObj = true; if (businessRules != null && newDataObjects != null) { if (businessRules.doesSearchObjectRequireNewParent()) { createNewDataObject(false); doSetNewDataObj = false; } for (Object dObj : newDataObjects) { if (!businessRules.isOkToAssociateSearchObject(parentDataObj, dObj)) { UIRegistry.showLocalizedError(businessRules.getMessagesAsString()); return; } businessRules.processSearchObject(!doSetNewDataObj ? dataObj : null, dObj); } // Set the data and validate this.setDataIntoUI(); if (formValidator != null) { formValidator.validateForm(); } } if (newDataObjects != null && newDataObjects.size() > 0) { if (doSetNewDataObj) { boolean doOtherSide = true; DBTableInfo parentTblInfo = DBTableIdMgr.getInstance() .getByShortClassName(parentDataObj.getClass().getSimpleName()); if (parentTblInfo != null) { DBTableChildIFace ci = parentTblInfo.getItemByName(cellName); if (ci instanceof DBRelationshipInfo) { DBRelationshipInfo ri = (DBRelationshipInfo) ci; doOtherSide = ri.getType() == DBRelationshipInfo.RelationshipType.OneToMany; } } for (Object obj : newDataObjects) { ((FormDataObjIFace) parentDataObj).addReference((FormDataObjIFace) obj, cellName, doOtherSide); } if (list != null && origDataSet != null) { list.addAll(newDataObjects); int len = list.size(); rsController.setLength(len); rsController.setIndex(len - 1, false); origDataSet.addAll(newDataObjects); } else { setDataObj(newDataObjects.get(0)); } mvParent.getTopLevel().getCurrentValidator().setHasChanged(true); mvParent.getTopLevel().getCurrentValidator().validateForm(); } } } } else { log.error("The search name is empty is there one defined in the display tag for the XML?"); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getSaveComponent() */ public JComponent getSaveComponent() { return saveControl; } //------------------------------------------------- // Viewable //------------------------------------------------- /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getType() */ public ViewDef.ViewType getType() { return formViewDef.getType(); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getUIComponent() */ public Component getUIComponent() { return mainComp; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#isSubform() */ public boolean isSubform() { return mvParent != null && mvParent.getMultiViewParent() != null; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getCompById(java.lang.String) */ @SuppressWarnings("unchecked") public <T> T getCompById(final String id) { FVOFieldInfo fi = controlsById.get(id); if (fi != null) { return (T) fi.getComp(); } // else //throw new RuntimeException("Couldn't find FieldInfo for ID["+id+"]"); //log.error("Couldn't find FieldInfo for ID["+id+"]"); return null; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getLabelById(java.lang.String) */ public JLabel getLabelFor(final String id) { FVOFieldInfo fi = labels.get(id); if (fi != null) { return (JLabel) fi.getComp(); } // else String msg = "Couldn't find FieldInfo for ID[" + id + "]"; log.error(msg); FormDevHelper.appendFormDevError(msg); return UIHelper.createLabel("Missing Label"); } /** * @param id the id of the label to be returned. * @return the FieldInfo for a label */ public FVOFieldInfo getLabelInfoFor(final String id) { for (FVOFieldInfo fi : labels.values()) { String labelForId = ((FormCellLabel) fi.getFormCell()).getLabelFor(); if (labelForId != null && labelForId.equals(id)) { return fi; } } return null; } /** * Get the label for a field comonent. * @param comp the field component * @return the label component for a field component */ public JLabel getLabelFor(final Component comp) { for (FVOFieldInfo fi : controlsById.values()) { if (fi.getComp() == comp) { return getLabelFor(fi.getId()); } } return null; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getControlMapping() */ public Map<String, Component> getControlMapping() { Map<String, Component> map = new Hashtable<String, Component>(); for (FVOFieldInfo fieldInfo : controlsById.values()) { map.put(fieldInfo.getId(), fieldInfo.getComp()); } return map; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#getControlById(java.lang.String) */ public Component getControlById(String id) { FVOFieldInfo fi = controlsById.get(id); return fi != null ? fi.getComp() : null; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.ViewBuilderIFace#hasRequiredFields() */ @Override public boolean hasRequiredFields() { return hasRequiredFields; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.ViewBuilderIFace#fixUpRequiredDerivedLabels() */ public void fixUpRequiredDerivedLabels() { // NOTE: The forms can contain object that are not in our data model DBTableInfo ti = DBTableIdMgr.getInstance().getByClassName(formViewDef.getClassName()); if (ti != null) { Font boldFont = null; for (String idFor : labels.keySet()) { FVOFieldInfo labelInfo = labels.get(idFor); JLabel label = (JLabel) labelInfo.getComp(); //FormCellLabelIFace lblCell = (FormCellLabelIFace)labelInfo.getFormCell(); FormViewObj.FVOFieldInfo fieldInfo = controlsById.get(idFor); if (fieldInfo == null) { FormDevHelper.appendFormDevError( "Setting Label -Form control with id[" + idFor + "] is not in the form or subform."); continue; } if (fieldInfo.getFormCell() != null && fieldInfo.getFormCell().getType() == FormCellIFace.CellType.field) { FormCellField cell = (FormCellField) fieldInfo.getFormCell(); String fieldName = fieldInfo.getFormCell().getName(); DBTableChildIFace derivedCI = null; if (fieldName.indexOf(".") > -1) { derivedCI = FormHelper.getChildInfoFromPath(fieldName, ti); if (derivedCI == null) { FormDevHelper.appendFormDevError("The name 'path' [" + fieldName + "] was not valid."); continue; } } DBTableChildIFace tblChild = derivedCI != null ? derivedCI : ti.getItemByName(fieldInfo.getFormCell().getName()); if (isEditing && (cell.isRequired() || (tblChild != null && tblChild.isRequired()))) { if (boldFont == null) { boldFont = label.getFont().deriveFont(Font.BOLD); } label.setFont(boldFont); } /*if (lblCell.isDerived() && tblChild != null) { String title = tblChild.getTitle(); if (StringUtils.isNotEmpty(title)) { label.setText(title + (StringUtils.isNotEmpty(title) ? ":" : "")); } }*/ } } /*for (FVOFieldInfo fieldInfo : controlsByName.values()) { if (fieldInfo.getFormCell().getType() == FormCellIFace.CellType.field) { FormCellField cell = (FormCellField)fieldInfo.getFormCell(); if (cell.getUiType() == FormCellFieldIFace.FieldType.checkbox) { DBFieldInfo fi = ti.getFieldByName(fieldInfo.getFormCell().getName()); JCheckBox cbx = (JCheckBox)fieldInfo.getComp(); if (isEditting && (cell.isRequired() || (fi != null && fi.isRequired()))) { if (boldFont == null) { boldFont = cbx.getFont().deriveFont(Font.BOLD); } cbx.setFont(boldFont); } if (cell.isDerived() && fi != null) { String title = fi.getTitle(); if (StringUtils.isNotEmpty(title)) { //cbx.setText(title); } } } } }*/ } } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.ViewBuilderIFace#doneBuilding() */ @Override public void doneBuilding() { for (UIPluginable plugin : uiPlugins) { plugin.setParent(this); } notifyUIPluginsOfChanges(false, isNewlyCreatedDataObj); } /** * @param id the id of the control * @return the FVOFieldInfo object by ID */ public FVOFieldInfo getFieldInfoForId(final String id) { return controlsById.get(id); } /** * @param fName the name of the control * @return the FVOFieldInfo object by name */ public FVOFieldInfo getFieldInfoForName(final String fName) { return controlsByName.get(fName); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getValidator() */ public FormValidator getValidator() { return formValidator; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#setDataObj(java.lang.Object) */ public void setDataObj(final Object dataObj) { setDataObj(dataObj, false); } /** * @param index * @return */ protected Object getDataObjectViaRecordSet(final int index) { Object dObj = null; //log.debug("Loading["+recordSetItemList.get(index).getRecordId()+"]"); DataProviderSessionIFace tmpSession = DataProviderFactory.getInstance().createSession(); try { dObj = tmpSession.get(tableInfo.getClassObj(), recordSetItemList.get(index).getRecordId()); ((FormDataObjIFace) dObj).forceLoad(); } catch (org.hibernate.ObjectNotFoundException hex) { hex.printStackTrace(); UIRegistry.showError("A data object could not be loaded:\n" + hex.toString()); } catch (Exception ex) { ex.printStackTrace(); edu.ku.brc.af.core.UsageTracker.incrHQLUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex); } finally { tmpSession.close(); } return dObj; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#setRecordSet(edu.ku.brc.dbsupport.RecordSetIFace) */ public void setRecordSet(final RecordSetIFace recordSet) { tableInfo = DBTableIdMgr.getInstance().getInfoById(recordSet.getDbTableId()); // XXX Check for Error here StringBuilder sql = new StringBuilder("SELECT " + tableInfo.getIdColumnName() + " FROM " + tableInfo.getName() + " WHERE " + tableInfo.getIdColumnName() + " IN ("); int cnt = 0; for (RecordSetItemIFace rsi : recordSet.getOrderedItems()) { if (cnt > 0) sql.append(','); sql.append(rsi.getRecordId()); cnt++; } sql.append(')'); if (cnt == 0) { UIRegistry.showLocalizedError("RS_HAS_NO_ITEMS", recordSet.getName()); return; } //log.debug(sql.toString()); SQLExecutionListener listener = new SQLExecutionListener() { public void exectionDone(final SQLExecutionProcessor process, final java.sql.ResultSet resultSet) { countResultsBack(recordSet, resultSet); } public void executionError(final SQLExecutionProcessor process, final Exception ex) { // Display dlg with error message } }; SQLExecutionProcessor sqlProc = new SQLExecutionProcessor(listener, sql.toString()); sqlProc.start(); } /** * @param fvo * @param availableIdList */ public void setRecordSetItemList(final DBTableInfo tableInfo, final List<RecordSetItemIFace> availableIdList) { if (availableIdList != null) { this.tableInfo = tableInfo; if (this.recordSetItemList == null) { recordSetItemList = new Vector<RecordSetItemIFace>(availableIdList.size()); } else { recordSetItemList.clear(); } if (recordSet == null) { RecordSetIFace rs = RecordSetFactory.getInstance().createRecordSet(); rs.setName("Temp"); rs.setDbTableId(tableInfo.getTableId()); recordSet = rs; } recordSetItemList.addAll(availableIdList); recordSet.addAll(availableIdList); } } /** * @param rs * @param resultSet */ protected void countResultsBack(final RecordSetIFace rs, final java.sql.ResultSet resultSet) { try { if (resultSet.next()) { HashSet<Integer> availableIdList = new HashSet<Integer>(); do { availableIdList.add(resultSet.getInt(1)); } while (resultSet.next()); if (availableIdList.size() != rs.getNumItems()) { UIRegistry.displayLocalizedStatusBarText("FormViewObj.NOT_ALL_RECS_FOUND"); } if (recordSet == null) { recordSet = RecordSetFactory.getInstance().createRecordSet(); } recordSetItemList = new Vector<RecordSetItemIFace>(availableIdList.size()); for (RecordSetItemIFace rsi : rs.getOrderedItems()) { if (availableIdList.contains(rsi.getRecordId())) { recordSetItemList.add(rsi); recordSet.addItem(rsi); } } Object firstDataObj = getDataObjectViaRecordSet(0); Vector<Object> tmpList = new Vector<Object>(availableIdList.size() + 5); tmpList.add(firstDataObj); for (int i = 1; i < recordSetItemList.size(); i++) { tmpList.add(null); } if (mvParent != null) { mvParent.setData(tmpList); mvParent.setRecordSetItemList(this, tableInfo, recordSetItemList); } else { setDataObj(tmpList); } } else { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JOptionPane.showMessageDialog(UIRegistry.getTopWindow(), getResourceString("NO_RECORD_FOUND"), getResourceString("NO_RECORD_FOUND_TITLE"), JOptionPane.WARNING_MESSAGE); } }); } } catch (SQLException ex) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JOptionPane.showMessageDialog(UIRegistry.getTopWindow(), getResourceString("ERROR_LOADING_FORM_DATA"), getResourceString("ERROR_LOADING_FORM_DATA_TITLE"), JOptionPane.WARNING_MESSAGE); } }); } } /** * Updates the enabled state of the New and delete buttons in the controller */ protected void updateControllerUI() { if (rsController != null) { rsController.updateUI(); } //log.debug("----------------- "+formViewDef.getName()+"----------------- "); if (delRecBtn != null && !isJavaCollection()) { boolean enableDelBtn = dataObj != null && (businessRules == null || businessRules.okToEnableDelete(this.dataObj)); //log.debug("1----------------- Del "+formViewDef.getName()+" "+enableDelBtn+"----------------- "); delRecBtn.setEnabled(enableDelBtn); } boolean enableNewBtn = false; if (newRecBtn != null) { if (formValidator != null && dataObj != null) { enableNewBtn = formValidator.isFormValid(); } else if (mvParent != null) { //log.debug("mvParent.getData() "+mvParent.getData() +" data ["+ (dataObj == null ? "null" : dataObj.getClass().getSimpleName()) + "] parent"+ // (!mvParent.isTopLevel() ? mvParent.getMultiViewParent().getData().getClass().getSimpleName() : "null")); if (mvParent.isTopLevel()) { enableNewBtn = true; } else { enableNewBtn = mvParent.getMultiViewParent() != null && mvParent.getMultiViewParent().getData() != null; } } //log.debug(view.getName()+" enableNewBtn "+enableNewBtn+" isNewlyCreatedDataObj "+isNewlyCreatedDataObj()+" ("+(enableNewBtn && (dataObj == null || !isNewlyCreatedDataObj()))+")"); // 03/27/08 - rods - Add isSingle check for SubForms that hold a single Object boolean isSingle = rsController == null && origDataSet == null; boolean newBtnEnabled = enableNewBtn && (dataObj == null || (!isNewlyCreatedDataObj() && !isSingle)); //log.debug("1----------------- Add "+formViewDef.getName()+" "+newBtnEnabled+"----------------- "); if (!isJavaCollection()) { newRecBtn.setEnabled(newBtnEnabled); } if (switcherUI != null) { switcherUI.setEnabled(enableNewBtn); } } if (srchRecBtn != null) { boolean enable = enableNewBtn && StringUtils.isNotBlank(searchName); srchRecBtn.setEnabled(enable); if (switcherUI != null) { switcherUI.setEnabled(enable); } } if (rsController != null && rsController.getSearchRecBtn() != null && switcherUI != null) { switcherUI.setEnabled(true); } } /** * Set the datObj into the form but controls * @param dataObj the data object * @param alreadyInTheList indicates whether this dataObj is already in the list of data objects we are working with */ @SuppressWarnings("unchecked") protected void setDataObj(final Object dataObj, final boolean alreadyInTheList) { // Setting up Carry Forward Object when the object already exists // usually from a search if (dataObj instanceof FormDataObjIFace && ((FormDataObjIFace) dataObj).getId() != null) { carryFwdDataObj = dataObj; } //log.debug("Setting DataObj["+dataObj+"]"); // rods - Added 3/21/08 because switching from the Grid View // back to the Form View causes the "+" button to be disabled and this // is because it thinks it is a newly created object for some reason isNewlyCreatedDataObj = false; // Convert the Set over to a List so the RecordController can be used Object data = dataObj; if (!alreadyInTheList) { if (data instanceof java.util.Set) { origDataSet = (Set) dataObj; List newList = Collections.list(Collections.enumeration(origDataSet)); data = newList; if (newList.size() > 0) { if (newList.get(0) instanceof Comparable<?>) { Collections.sort(newList); } } } } // If there is a formValidator then we set the current object into the formValidator's scripting context // then turn off change notification while the form is filled if (formValidator != null && dataObj != null) { formValidator.addRuleObjectMapping("dataObj", dataObj); } if (selectorCBX != null) { selectorCBX.setEnabled(true); } boolean isList; boolean isVector; // if we do have a list then get the first object or null if (data instanceof Vector) { isList = true; isVector = true; } else if (data instanceof List) { isList = true; isVector = false; } else { isList = false; isVector = false; } for (FVOFieldInfo fieldInfo : controlsById.values()) { if (fieldInfo.isOfType(FormCellIFace.CellType.subview) || fieldInfo.isOfType(FormCellIFace.CellType.iconview)) { MultiView mv = fieldInfo.getSubView(); if (mv != null) { mv.setParentDataObj(null); } else { ((SubViewBtn) fieldInfo.getComp()).setParentDataObj(null); } } /*if (isEditing && fieldInfo.getComp() instanceof EditViewCompSwitcherPanel) { if (isDataValueNew) { ((EditViewCompSwitcherPanel)fieldInfo.getComp()).putIntoEditMode(); } else { ((EditViewCompSwitcherPanel)fieldInfo.getComp()).putIntoViewMode(); } }*/ } // if we do have a list then get the first object or null if (isList) { if (isVector) { list = (Vector) data; } else { list = new Vector<Object>((List<?>) data); } if (list.size() > 0) { this.dataObj = list.get(0); carryFwdDataObj = this.dataObj; //log.debug("Getting DO from list "+this.dataObj.getClass().getSimpleName()+" "+this.dataObj.hashCode()); } else { this.dataObj = null; } // Now tell the RecordController how many Object we have if (rsController != null) { int len = list.size(); if (AppContextMgr.isSecurityOn()) { ensurePermissions(); if (perm.hasNoPerm()) { len = 0; } } rsController.setLength(len); //updateControllerUI(); } // Set the data from the into the form setDataIntoUI(); } else { // OK, it is a single data object this.dataObj = dataObj; if (!alreadyInTheList && (this.list != null && this.dataObj != dataObj)) { this.list = null; } setDataIntoUI(); // Don't remove the rsController if the data is NULL because the next non-null one may be a list // mostly likely it will be if (rsController != null) { if (this.dataObj != null) { // I added this 'if' and I have no idea why the call was here in the first place. - rods // was it here for PaleoContext ????? if (!alreadyInTheList) { //controlPanel.setRSCVisibility(!isEditting); rsController.reset(); // rods - 07/07/08 just moved this into the this 'if' statement // it has already caused problems not being n there. } } else { rsController.clear(); } updateControllerUI(); } } } /** * Discards the current data object in the form. It may have been added to the List/Set * and need to be removed. * @param throwAway indicates whether it should throw or reload the data object. */ public void discardCurrentObject(final boolean throwAway) { if (parentDataObj instanceof FormDataObjIFace) { ((FormDataObjIFace) parentDataObj).removeReference((FormDataObjIFace) dataObj, cellName); } if (throwAway || (dataObj instanceof FormDataObjIFace && ((FormDataObjIFace) dataObj).getId() == null)) { if (list != null) { list.remove(dataObj); int len = list.size(); rsController.setLength(len); rsController.setIndex(len - 1, false); } // I am punting here and just removing the last one if (recordSetItemList != null && recordSetItemList.size() > 0) { recordSetItemList.remove(recordSetItemList.size() - 1); } } else if (dataObj instanceof FormDataObjIFace) { reloadDataObj(); } else { setDataIntoUI(); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getDataObj() */ public Object getDataObj() { //log.debug("getDataObj " + this.getView().getName()); return dataObj; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#setParentDataObj(java.lang.Object) */ public void setParentDataObj(Object parentDataObj) { this.parentDataObj = parentDataObj; //updateControllerUI(); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getParentDataObj() */ public Object getParentDataObj() { return parentDataObj; } /** * @param enabled */ public void setFormEnabled(final boolean enabled) { // Enable the labels for (FVOFieldInfo labelFI : labels.values()) { labelFI.getComp().setEnabled(true); } // Enable the form controls for (FVOFieldInfo compFI : controlsById.values()) { compFI.setEnabled(true); } /*if (!enabled) { for (MultiView kid : kids) { if (kid.getCurrentViewAsFormViewObj() != null) { kid.getCurrentViewAsFormViewObj().setFormEnabled(enabled); } } }*/ } /** * @return the isCreatingNewObject */ public boolean isCreatingNewObject() { return isCreatingNewObject; } /** * @param isCreatingNewObject the isCreatingNewObject to set */ public void setCreatingNewObject(boolean isCreatingNewObject) { this.isCreatingNewObject = isCreatingNewObject; } /** * @return the actual value of isNewlyCreatedDataObj */ public boolean getIsNewlyCreatedDataObj() { return isNewlyCreatedDataObj; } /** * @return the the top-levels value of isNewlyCreatedDataObj or it's own isNewlyCreatedDataObj if it is the top-level ro one doesn't exist. */ public boolean isNewlyCreatedDataObj() { return (mvParent != null && mvParent.isTopLevel()) ? mvParent.getCurrentViewAsFormViewObj().getIsNewlyCreatedDataObj() : isNewlyCreatedDataObj; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#setDataIntoUI() */ public void setDataIntoUI() { setDataIntoUI(true, false); } /** * Makes sure we have gotten the permissions. */ private void ensurePermissions() { // Make sure we get the right class name, the dataObj is sometimes a "Set<?>" if (perm == null) { String shortClassName = MultiView.getClassNameFromParentMV(dataClass, mvParent, cellName); if (StringUtils.isEmpty(shortClassName)) { if (classToCreate == null) { try { shortClassName = Class.forName(view.getClassName()).getSimpleName(); } catch (Exception ex) { shortClassName = dataObj.getClass().getSimpleName(); } } else { shortClassName = classToCreate.getSimpleName(); } } if ("ObjectAttachmentIFace".equals(shortClassName)) { // This is a kludge. The attachment form specifies the above interface for its class, // but we probably want to use the permissions for the actual table. Especially since there // are no permissions defined for the interface! shortClassName = dataObj.getClass().getSimpleName(); } perm = SecurityMgr.getInstance().getPermission("DO." + shortClassName.toLowerCase()); } } /** * * @return true skip session.attach, false do it */ public boolean isSkippingAttach() { return isSkippingAttach; } /** * Set this to true if you do not want the form to do an attach before filling in the entire form * * @param isSkippingAttach true skip session.attach, false do it */ public void setSkippingAttach(final boolean isSkippingAttach) { this.isSkippingAttach = isSkippingAttach; for (FVOFieldInfo fi : controlsById.values()) { if (fi.getFormCell() instanceof FormCellSubView) { if (fi.getComp() instanceof SubViewBtn) { ((SubViewBtn) fi.getComp()).setSkippingAttach(isSkippingAttach); } else if (fi.getSubView() != null) { if (fi.getSubView().getCurrentView() != null) { fi.getSubView().getCurrentView().setSkippingAttach(isSkippingAttach); } } } } } /** * Fill the form with data, indicate whether the form should be reset because the data is new. * @param doResetAfterFill tells the form to be reset after filling, as if it was new data. * */ protected void setDataIntoUI(final boolean doResetAfterFill, final boolean forceCreateSession) { if (formViewDef == null) { return; } if (dataObj != null) { if (AppContextMgr.isSecurityOn()) { ensurePermissions(); if ((isEditing && perm.isViewOnly()) || (!isEditing && !perm.canView())) { return; } } } if (businessRules != null) { businessRules.beforeFormFill(); } if (!isSkippingAttach && dataObj != null && dataObj instanceof FormDataObjIFace && ((FormDataObjIFace) dataObj).getId() != null) { if (mvParent == null || mvParent.isTopLevel() || forceCreateSession) { if (session != null) { session.close(); } setSession(DataProviderFactory.getInstance().createSession()); if (session != null && mvParent != null) { mvParent.setSession(session); } try { if (mvParent == null || mvParent.isTopLevel()) { session.attach(dataObj); ((FormDataObjIFace) dataObj).forceLoad(); } } catch (HibernateException ex) { edu.ku.brc.af.core.UsageTracker.incrHQLUsageCount(); //edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex); //Oh No! //take the drastic measures in the unreachable else block below... Object beforeSaveDataObj = dataObj; try { dataObj = session.merge(dataObj); } catch (TypeMismatchException tmmex) { try { session.saveOrUpdate(dataObj); } catch (Exception ex2) { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex2); throw new RuntimeException(ex2); } } catch (Exception ex2) { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex2); throw new RuntimeException(ex2); } replaceDataObjInList(beforeSaveDataObj, dataObj); if (origDataSet != null) { origDataSet.remove(beforeSaveDataObj); origDataSet.add(dataObj); } } } } // Now turn off data change notification and then validate the form if (formValidator != null) { formValidator.setDataChangeNotification(false); formValidator.setEnabled(dataObj != null); if (dataObj == null) { formValidator.setState(UIValidatable.ErrorType.Valid); } // I have always wanted to avoid doing this globally // but it is the best approach UIValidator.setIgnoreAllValidation(this, true); } boolean weHaveData = true; DataObjectGettable dg = formViewDef.getDataGettable(); // This is a short circut for when we were switch from being enabled to disabled or visa-versus // This way we won't need to set the controls enabled or disabled each time we advance to a new record, // we only have to do it once if (dataObj == null && !wasNull) { // Disable all the labels for (FVOFieldInfo labelFI : labels.values()) { labelFI.getComp().setEnabled(false); } // Disable all the form controls and set their values to NULL for (FVOFieldInfo fieldInfo : controlsById.values()) { fieldInfo.getComp().setEnabled(false); if (fieldInfo.isOfType(FormCellIFace.CellType.field)) { setDataIntoUIComp(fieldInfo.getComp(), null, null); //log.debug("Setting ["+fieldInfo.getName()+"] to enabled=false"); } else if (fieldInfo.isOfType(FormCellIFace.CellType.subview)) { MultiView mv = fieldInfo.getSubView(); if (mv != null) { mv.setData(null); } else { setDataIntoUIComp(fieldInfo.getComp(), null, null); } } } // Disable the ResultSet Controller if (rsController != null) { rsController.clear(); } wasNull = true; weHaveData = false; } else if (dataObj != null && wasNull) { setFormEnabled(true); // Enable the ResultSet Controller if (rsController != null) { rsController.reset(); } wasNull = false; } if (draggableRecIdentifier != null && this.dataObj != null && this.dataObj instanceof FormDataObjIFace) { FormDataObjIFace formDataObj = (FormDataObjIFace) this.dataObj; draggableRecIdentifier.setFormDataObj(formDataObj); } boolean hasDefaultAnywhere = false; if (weHaveData) { Object[] defaultDataArray = new Object[1]; // needed for setting the default value // Now we know the we have data, so loop through all the controls // and set their values for (FVOFieldInfo fieldInfo : controlsById.values()) { Component comp = fieldInfo.getComp(); Object data = null; // This is for panels that use in layout but have no data if (fieldInfo.isOfType(FormCellIFace.CellType.field)) { // Do Formatting here FormCellField cellField = (FormCellField) fieldInfo.getFormCell(); // 02/13/08 - ignore means ignore if (cellField.isIgnoreSetGet()) { continue; } String dataObjFormatName = cellField.getFormatName(); String defaultValue = isEditing() ? cellField.getDefaultValue() : null; boolean hasID = dataObj instanceof FormDataObjIFace && ((FormDataObjIFace) dataObj).getId() != null; //log.debug("["+cellField.getName()+"] hasID["+hasID+"] defaultValue["+defaultValue+"] hasDefault["+hasDefaultAnywhere+"]"); if (!hasDefaultAnywhere && this.dataObj != null && !hasID && StringUtils.isNotEmpty(defaultValue)) { hasDefaultAnywhere = true; } boolean isTextFieldPerMode = cellField.isTextFieldForMode(altView.getMode()); boolean useDataObjFormatName = isTextFieldPerMode && isNotEmpty(dataObjFormatName); //log.debug("["+cellField.getName()+"] useFormatName["+useFormatName+"] "+comp.getClass().getSimpleName()); if (useDataObjFormatName) { if (cellField.getFieldNames().length > 1) { throw new RuntimeException( "formatName [" + dataObjFormatName + "] only works on a single value."); } Object[] values = UIHelper.getFieldValues(cellField.getFieldNames(), dataObj, dg); setDataIntoUIComp(comp, DataObjFieldFormatMgr.getInstance().format(values[0], dataObjFormatName), defaultValue); } else { Object[] values; if (((FormCellFieldIFace) fieldInfo.getFormCell()).useThisData()) { values = new Object[] { dataObj }; } else if (fieldInfo.getFormCell().isIgnoreSetGet()) { defaultDataArray[0] = defaultValue; values = defaultDataArray; } else { values = UIHelper.getFieldValues(cellField, dataObj, dg); } if (values != null && values.length > 0) { String format = cellField.getFormat(); if (tableInfo != null && isEmpty(format)) { DBFieldInfo fi = tableInfo.getFieldByName(fieldInfo.getFormCell().getName()); if (fi != null) { format = fi.getFormatStr(); } } if (isNotEmpty(format)) { setDataIntoUIComp(comp, UIHelper.getFormattedValue(format, values), defaultValue); } else { if (cellField.getFieldNames().length > 1) { throw new RuntimeException("No Format but multiple fields were specified for[" + cellField.getName() + "]"); } if (values[0] == null) { setDataIntoUIComp(comp, isTextFieldPerMode ? "" : null, defaultValue); } else { setDataIntoUIComp(comp, isTextFieldPerMode && !(values[0] instanceof Number) ? values[0].toString() : values[0], defaultValue); } } } else { setDataIntoUIComp(comp, null, defaultValue); } } } else if (fieldInfo.isOfType(FormCellIFace.CellType.subview)) { if (fieldInfo.getFormCell().isIgnoreSetGet()) { continue; } MultiView mv = fieldInfo.getSubView(); if (mv != null) { mv.setParentDataObj(dataObj); } else { ((SubViewBtn) fieldInfo.getComp()).setParentDataObj(dataObj); } try // XXX RELEASE remove try block { Object[] values = UIHelper.getFieldValues(fieldInfo.getFormCell(), dataObj, dg); data = values != null ? values[0] : null; } catch (NullPointerException ex) { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex); FormDevHelper.appendFormDevError( "FieldCell[" + fieldInfo.getFormCell().getName() + " data[" + dataObj + "]"); return; } if (data != null) { if (((FormCellSubViewIFace) fieldInfo.getFormCell()).isSingleValueFromSet() && data instanceof Set<?>) { Set<?> set = (Set<?>) data; if (set.size() > 0) { data = set.iterator().next(); } } if (mv != null) { mv.setData(data); } else { ((SubViewBtn) fieldInfo.getComp()).setValue(data, null); } } else if (fieldInfo.getComp() instanceof MultiView) { ((MultiView) fieldInfo.getComp()).setData(data); } else { ((SubViewBtn) fieldInfo.getComp()).setValue(data, null); } } if (fieldInfo.getComp() instanceof EditViewCompSwitcherPanel) { boolean isOK = !(dataObj instanceof FormDataObjIFace) || ((FormDataObjIFace) dataObj).getId() == null; if (isEditing && isOK) { ((EditViewCompSwitcherPanel) fieldInfo.getComp()).putIntoEditMode(); } else { ((EditViewCompSwitcherPanel) fieldInfo.getComp()).putIntoViewMode(); } } } } // Adjust the formValidator now that all the data is in the controls //boolean doReset = !hasDefault || formValidator == null || !formValidator.hasChanged(); /*if (dataObj != null) { System.out.println("hasDefault: "+hasDefault + " doResetAfterFill: "+doResetAfterFill+" "+(formValidator != null ? formValidator.getName() :"")); } else { System.out.println("hasDefault: "+hasDefault); }*/ if (formValidator != null) { if (this.dataObj == null || (!hasDefaultAnywhere && doResetAfterFill)) { formValidator.reset(MultiView.isOptionOn(options, MultiView.IS_NEW_OBJECT)); } else { formValidator.setHasChanged(true); } } if (businessRules != null) { businessRules.afterFillForm(dataObj); } if (AppContextMgr.isSecurityOn() && dataObj != null && mvParent != null && mvParent.isEditable()) { processControlsForSecurity(dataObj); } //if (doResetAfterFill && mvParent != null && mvParent.isTopLevel() && saveControl != null && isEditing) //{ // saveControl.setEnabled(false); //} // See comment above where I turn this on if (formValidator != null) { UIValidator.setIgnoreAllValidation(this, false); } updateControllerUI(); if (session != null && (mvParent == null || mvParent.isTopLevel() || forceCreateSession)) { session.close(); setSession(null); if (mvParent != null) { mvParent.setSession(session); } } } /** * @param dataObj */ protected void processControlsForSecurity(Object dataObj) { boolean editable = checkEditPermission(dataObj); for (String id : controlsById.keySet()) { //In case business rules have intentionally disabled controls. (bug 10068) Component cmp = getControlById(id); cmp.setEnabled(cmp.isEnabled() && editable); //The old way: //getControlById(id).setEnabled(editable); } } /** * @param dataObj * @return true if current user has permission to save. */ protected boolean checkEditPermission(Object dataObj) { if (dataObj instanceof DataModelObjBase) { return (perm.canModify() || (perm.canAdd() && ((DataModelObjBase) dataObj).getId() == null)); } return true; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getDataFromUI() */ @Override public void getDataFromUI() { if (isEditing) { // This should only happen when the user created a new object // in a form in a dialog and then they pressed Cancel without it being saved. /*if (isNewlyCreatedDataObj) { if (parentDataObj instanceof FormDataObjIFace) { ((FormDataObjIFace)parentDataObj).addReference((FormDataObjIFace)dataObj, cellName); } else { FormHelper.addToParent(parentDataObj, dataObj); } isNewlyCreatedDataObj = false; }*/ if (formValidator != null && formValidator.getState() != UIValidatable.ErrorType.Valid) { if (isNewlyCreatedDataObj) { if (list != null) { list.remove(dataObj); } if (origDataSet != null) { origDataSet.remove(dataObj); } formValidator.setFormValidationState(UIValidatable.ErrorType.Valid); formValidator.reset(true); formValidator.validateRoot(); } return; } DataObjectSettable ds = formViewDef.getDataSettable(); DataObjectGettable dg = formViewDef.getDataGettable(); if (ds != null) { // Get Data From Selector if (selectorCBX != null) { String selectorName = altView.getSelectorName(); if (StringUtils.isNotEmpty(selectorName)) { try { PropertyDescriptor descr = PropertyUtils.getPropertyDescriptor(dataObj, selectorName); Object selectorValObj = UIHelper.convertDataFromString(altView.getSelectorValue(), descr.getPropertyType()); FormHelper.setFieldValue(selectorName, dataObj, selectorValObj, dg, ds); } catch (Exception ex) { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex); log.error(ex); // XXX TODO Show error dialog here } } } for (FVOFieldInfo fieldInfo : controlsById.values()) { //String nm = fieldInfo.getFormCell().getName(); //System.out.println(nm); FormCellIFace fc = fieldInfo.getFormCell(); boolean isInoreGetSet = fc.isIgnoreSetGet(); boolean isReadOnly; boolean useThisData; // meaning the control is using the same data object as what is in the form // so we don't need to go get the data (skip it) if (fc instanceof FormCellField) { FormCellFieldIFace fcf = (FormCellFieldIFace) fc; isReadOnly = fcf.isReadOnly();// || fcf.isEditOnCreate(); useThisData = fcf.useThisData(); } else { useThisData = false; isReadOnly = false; } String id = fieldInfo.getFormCell().getIdent(); boolean hasFormControlChanged = hasFormControlChanged(id); //log.debug(fieldInfo.getName()+"\t"+fieldInfo.getFormCell().getName()+"\t hasChanged: "+(!isReadOnly && hasFormControlChanged)); if (!isReadOnly && !isInoreGetSet && (hasFormControlChanged || isAlwaysGetDataFromUI)) { // this ends up calling the getData on the GetSetValueIFace // which enables the control to set data into the data object if (useThisData) { getDataFromUIComp(id); continue; } boolean isSubView = fieldInfo.getFormCell() instanceof FormCellSubViewIFace; if (isSubView && fieldInfo.getComp() instanceof MultiView) { MultiView mv = (MultiView) fieldInfo.getComp(); mv.getDataFromUI(); } //log.debug(fieldInfo.getName()+" "+fieldInfo.getFormCell().getName() +" HAS CHANGED!"); Object uiData = getDataFromUIComp(id); // if ID is null then we have huge problems // if (uiData != null && dataObj != null) Changed for Bug 4994 if (dataObj != null) { if (isSubView) { log.debug(fieldInfo.getFormCell().getName()); if (uiData != null) { FormHelper.setFieldValue(fieldInfo.getFormCell().getName(), dataObj, uiData, dg, ds); } } else { //log.info(fieldInfo.getFormCell().getName()+" "+(dataObj != null ? dataObj.getClass().getSimpleName() : "dataObj was null")); FormHelper.setFieldValue(fieldInfo.getFormCell().getName(), dataObj, uiData, dg, ds); } } } } } else { throw new RuntimeException( "Calling getDataFromUI when the DataObjectSettable is null for the form."); } } } /** * If the control supports UIValidatable interface then it return whether the controls has been changed. If it * doesn't then it assumes it has and returns true. * @param id the id of the control * @return If the control supports UIValidatable interface then it return whether the controls has been changed. If it * doesn't then it assumes it has and returns true. */ public boolean hasFormControlChanged(final String id) { FVOFieldInfo fieldInfo = controlsById.get(id); if (fieldInfo != null) { Component comp = fieldInfo.getComp(); if (comp != null) { if (comp instanceof UIValidatable) { boolean hasChanged = ((UIValidatable) comp).isChanged(); if (!hasChanged && comp instanceof AutoNumberableIFace) { hasChanged = true; return hasChanged; } boolean hasDefaultData = false; if (fieldInfo.getFormCell() instanceof FormCellFieldIFace) { hasDefaultData = StringUtils .isNotEmpty(((FormCellFieldIFace) fieldInfo.getFormCell()).getDefaultValue()); } return ((UIValidatable) comp).isChanged() || hasDefaultData; } } } return true; } /** * @return whether it is in Edit Mode */ public boolean isEditing() { return isEditing; } /** * @param comp * @param isSingleValueFromSet * @param isCommand * @param id * @return */ public static Object getValueFromComponent(final Component comp, final boolean isSingleValueFromSet, final boolean isCommand, final String id) { if (comp != null) { if (comp instanceof GetSetValueIFace) { return ((GetSetValueIFace) comp).getValue(); } else if (comp instanceof MultiView) { if (isSingleValueFromSet) { return ((MultiView) comp).getData(); } // else return null; } else if (comp instanceof JTextField) { return ((JTextField) comp).getText(); } else if (comp instanceof JComboBox) { if (comp instanceof JAutoCompComboBox) { PickListItemIFace pli = (PickListItemIFace) ((JAutoCompComboBox) comp).getSelectedItem(); return pli.getValueObject() == null ? pli.getValue() : pli.getValueObject(); } // else return ((JComboBox) comp).getSelectedItem().toString(); } else if (comp instanceof JLabel) { return ((JLabel) comp).getText(); } else if (comp instanceof ColorChooser) { return ColorWrapper.toString(((ColorChooser) comp).getBackground()); } else if (comp instanceof JList) { return ((JList) comp).getSelectedValue().toString(); } else if (comp instanceof JCheckBox) { return new Boolean(((JCheckBox) comp).isSelected()); } else if (isCommand) { // no op } else { log.error("Not sure how to get data from object " + comp); } } else { log.error("Component is null in FieldInfo " + id); } return null; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getDataFromUIComp(java.lang.String) */ @Override public Object getDataFromUIComp(final String id) { FVOFieldInfo fieldInfo = controlsById.get(id); if (fieldInfo != null) { boolean isSingleValueFromSet = false; if (fieldInfo.getFormCell() instanceof FormCellSubViewIFace) { isSingleValueFromSet = ((FormCellSubViewIFace) fieldInfo.getFormCell()).isSingleValueFromSet(); } return getValueFromComponent(fieldInfo.getComp(), isSingleValueFromSet, fieldInfo.getFormCell().getType() == FormCellIFace.CellType.command, id); } log.error("FieldInfo is null " + id); return null; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getSubView(java.lang.String) */ @Override public MultiView getSubView(final String name) { // do linear search because there will never be very many of them for (MultiView mv : kids) { if (mv.getViewName().equals(name)) { return mv; } } return null; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#setDataIntoUIComp(java.lang.String, java.lang.Object) */ @Override public void setDataIntoUIComp(final String id, Object data) { setDataIntoUIComp(controlsById.get(id).getComp(), data, null); } /** * Helper class to set data into a component * @param comp the component to get the data * @param data the data to be set into the component */ public static void setDataIntoUIComp(final Component comp, final Object data, final String defaultValue) { if (comp instanceof GetSetValueIFace) { ((GetSetValueIFace) comp).setValue(data, defaultValue); } else if (comp instanceof MultiView) { ((MultiView) comp).setData(data); } else if (comp instanceof JTextField) { JTextField tf = (JTextField) comp; tf.setText(data == null ? "" : data.toString()); tf.setCaretPosition(0); } else if (comp instanceof JTextArea) { //log.debug(name+" - "+comp.getPreferredSize()+comp.getSize()); ((JTextArea) comp).setText(data == null ? "" : data.toString()); } else if (comp instanceof JCheckBox) { //log.debug(name+" - "+comp.getPreferredSize()+comp.getSize()); if (data != null) { ((JCheckBox) comp).setSelected((data instanceof Boolean) ? ((Boolean) data).booleanValue() : data.toString().equalsIgnoreCase("true")); } else { ((JCheckBox) comp).setSelected(false); } } else if (comp instanceof JLabel) { ((JLabel) comp).setText(data == null ? "" : data.toString()); } else if (comp instanceof JComboBox) { setComboboxValue((JComboBox) comp, data); } else if (comp instanceof JList) { setListValue((JList) comp, data); } // Reset it's state as not being changes, // because setting in data will cause the change flag to be set if (comp instanceof UIValidatable && StringUtils.isEmpty(defaultValue)) { ((UIValidatable) comp).setChanged(false); } } /** * Sets the appropriate index in the combobox for the value * @param comboBox the combobox * @param data the data value */ protected static void setComboboxValue(final JComboBox comboBox, final Object data) { ComboBoxModel model = comboBox.getModel(); for (int i = 0; i < comboBox.getItemCount(); i++) { Object item = model.getElementAt(i); if (item instanceof String) { if (((String) item).equals(data)) { comboBox.setSelectedIndex(i); break; } } else if (item.equals(data)) { comboBox.setSelectedIndex(i); break; } } } /** * Sets the appropriate index in the list box * @param list the list box * @param data the data value */ protected static void setListValue(final JList list, final Object data) { Iterator<?> iter = null; if (data instanceof Set<?>) { iter = ((Set<?>) data).iterator(); } else if (data instanceof org.hibernate.collection.PersistentSet) { iter = ((org.hibernate.collection.PersistentSet) data).iterator(); } if (iter != null) { DefaultListModel defModel = new DefaultListModel(); while (iter.hasNext()) { defModel.addElement(iter.next()); } list.setModel(defModel); } else { ListModel model = list.getModel(); for (int i = 0; i < model.getSize(); i++) { Object item = model.getElementAt(i); if (item instanceof String) { if (((String) item).equals(data)) { list.setSelectedIndex(i); return; } } else if (item.equals(data)) { list.setSelectedIndex(i); return; } } } } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.Viewable#getControllerPanel() */ @Override public JComponent getControllerPanel() { return sepController == null || sepController.getComponentCount() == 0 ? null : sepController; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getView() */ @Override public ViewIFace getView() { return view; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#hideMultiViewSwitch(boolean) */ @Override public void hideMultiViewSwitch(boolean hide) { if (switcherUI != null) { switcherUI.setVisible(!hide); } } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.Viewable#enableMultiViewSwitch(boolean) */ @Override public void enableMultiViewSwitch(boolean enabled) { if (switcherUI != null) { switcherUI.setEnabled(enabled); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#dataHasChanged() */ @Override public void validationWasOK(boolean wasOK) { if (saveControl != null && (mvParent == null || mvParent.hasChanged())) { saveControl.setEnabled(wasOK); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#setSession(org.hibernate.Session) */ @Override public void setSession(final DataProviderSessionIFace session) { //log.debug("setSession "+hashCode() + " Session ["+(session != null ? session.hashCode() : "null")+"] "); this.session = session; if (sessionListeners != null) { for (SessionListenerIFace sli : sessionListeners) { sli.setSession(session); } } } /** * @return the session */ public DataProviderSessionIFace getSession() { return session; } /** * @param sli */ public void addSessionListener(final SessionListenerIFace sli) { if (sessionListeners == null) { sessionListeners = new Vector<SessionListenerIFace>(); } sessionListeners.add(sli); } /** * @param sli */ public void removeSessionListener(final SessionListenerIFace sli) { if (sessionListeners != null) { sessionListeners.remove(sli); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#setCellName(java.lang.String) */ @Override public void setCellName(final String cellName) { this.cellName = cellName; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#registerSaveBtn(javax.swing.JButton) */ @Override public void registerSaveBtn(final JButton saveBtnArg) { this.saveControl = saveBtnArg; this.saveControl.setOpaque(false); if (formValidator != null) { formValidator.addEnableItem(saveControl, FormValidator.EnableType.ValidAndChangedItems); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#updateSaveBtn() */ @Override public void updateSaveBtn() { if (saveControl != null && formValidator != null) { if (mvParent == null || mvParent.isAllValidationOK()) { validationWasOK(formValidator.getState() == UIValidatable.ErrorType.Valid); } } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#focus() */ @Override public void focus() { if (mainComp != null) { mainComp.requestFocus(); } focusFirstFormControl(); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#aboutToShutdown() */ @Override public void aboutToShutdown() { if (businessRules != null) { businessRules.aboutToShutdown(); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#shutdown() */ @Override public void shutdown() { for (Enumeration<FVOFieldInfo> e = controlsById.elements(); e.hasMoreElements();) { FVOFieldInfo fieldInfo = e.nextElement(); fieldInfo.shutdown(); } compsList.clear(); controlsById.clear(); controlsByName.clear(); labels.clear(); if (sessionListeners != null) { sessionListeners.clear(); } if (altViewsList != null) { altViewsList.clear(); } kids.clear(); uiPlugins.clear(); mvParent = null; formViewDef = null; formComp = null; if (formValidator != null) { formValidator.removeValidationListener(this); FormValidator parent = formValidator.getParent(); if (parent != null) { parent.remove(formValidator); } formValidator.setParent(null); } if (businessRules != null) { businessRules.formShutdown(); businessRules = null; } } //------------------------------------------------- // ViewBuilderIFace //------------------------------------------------- /** * Adds a control by name so it can be looked up later. * @param formCell the FormCell def that describe the cell * @param label the the label to be added */ public void addLabel(final FormCellLabel formCell, final JLabel label) { if (formCell != null) { if (StringUtils.isNotEmpty(formCell.getLabelFor())) { if (labels.get(formCell.getLabelFor()) != null) { String msg = "Two labels have the same id [" + formCell.getLabelFor() + "] " + formViewDef.getName(); FormDevHelper.showFormDevError(msg); } labels.put(formCell.getLabelFor(), new FVOFieldInfo(formCell, label, null, labels.size())); } allLabels.put(formCell.getIdent(), label); } } /** * Gets a label by id. * @param id the id * @return the JLabel */ public JLabel getLabelById(final String id) { return allLabels.get(id); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#registerControl(edu.ku.brc.ui.forms.persist.FormCellIFace, java.awt.Component) */ @Override public void registerControl(final FormCellIFace formCell, final Component control) { if (formCell != null) { boolean isThis = formCell.getName().equals("this"); if (controlsById.get(formCell.getIdent()) != null) { throw new RuntimeException( "Two controls have the same id [" + formCell.getIdent() + "] " + formViewDef.getName()); } if (!isThis && controlsByName.get(formCell.getName()) != null) { throw new RuntimeException( "Two controls have the same name [" + formCell.getName() + "] " + formViewDef.getName()); } if (!hasRequiredFields && formCell instanceof FormCellFieldIFace && ((FormCellFieldIFace) formCell).isRequired()) { hasRequiredFields = true; } JScrollPane scrPane; Component comp; if (control instanceof JScrollPane) { scrPane = (JScrollPane) control; comp = scrPane.getViewport().getView(); } else { scrPane = null; comp = control; } FVOFieldInfo fieldInfo = new FVOFieldInfo(formCell, comp, scrPane, controlsById.size()); controlsById.put(formCell.getIdent(), fieldInfo); if (!isThis) { controlsByName.put(formCell.getName(), fieldInfo); } compsList.add(fieldInfo); if (comp instanceof FormControlSaveable) { saveableList.add((FormControlSaveable) comp); } } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#registerPlugin(edu.ku.brc.ui.forms.persist.FormCellIFace, edu.ku.brc.af.ui.forms.UIPluginable) */ @Override public void registerPlugin(final FormCellIFace formCell, final UIPluginable uip) { boolean isThis = formCell.getName().equals("this"); if (controlsById.get(formCell.getIdent()) != null) { throw new RuntimeException( "Two controls have the same id [" + formCell.getIdent() + "] " + formViewDef.getName()); } if (!isThis && controlsByName.get(formCell.getName()) != null) { throw new RuntimeException( "Two controls have the same name [" + formCell.getName() + "] " + formViewDef.getName()); } uip.addPropertyChangeListener(this); FVOFieldInfo fieldInfo = new FVOFieldInfo(formCell, uip, controlsById.size()); controlsById.put(formCell.getIdent(), fieldInfo); if (!isThis) { controlsByName.put(formCell.getName(), fieldInfo); compsList.add(fieldInfo); } if (uip.getUIComponent() instanceof FormControlSaveable) { saveableList.add((FormControlSaveable) uip.getUIComponent()); } uiPlugins.add(uip); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#addControlToUI(java.awt.Component, int, int, int, int) */ @Override public void addControlToUI(Component control, int colInx, int rowInx, int colSpan, int rowSpan) { if (control instanceof SessionListenerIFace) { addSessionListener((SessionListenerIFace) control); } builder.add(control, cc.xywh(colInx, rowInx, colSpan, rowSpan)); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#createSeparator(java.lang.String) */ @Override public Component createSeparator(String title) { int titleAlignment = builder.isLeftToRight() ? SwingConstants.LEFT : SwingConstants.RIGHT; JComponent titledSeparator = builder.getComponentFactory().createSeparator(title, titleAlignment); setControlSize(titledSeparator); return titledSeparator; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#addRecordIndentifier(java.lang.String, javax.swing.ImageIcon) */ @Override public JComponent createRecordIndentifier(String title, ImageIcon icon) { PanelBuilder panelBldr = new PanelBuilder(new FormLayout("16px,1px,f:p:g", "p")); draggableRecIdentifier = DraggableRecordIdentifierFactory.getInstance() .createDraggableRecordIdentifier(icon); //draggableRecIdentifier.setLabel(title); panelBldr.add(draggableRecIdentifier, cc.xy(1, 1)); panelBldr.addSeparator(title, cc.xy(3, 1)); return panelBldr.getPanel(); } /** * Adds a control by name so it can be looked up later * @param formCell the FormCell def that describe the cell * @param subView the subView * @param colInx column index * @param rowInx row index * @param colSpan column span * @param rowSpan row span * @param addIt add it to the layout */ public void addSubView(final FormCellSubView formCell, final MultiView subView, final int colInx, final int rowInx, final int colSpan, final int rowSpan, final boolean addIt) { if (formCell != null) { if (controlsById.get(formCell.getIdent()) != null) { UIRegistry.showError( "Two controls have the same id [" + formCell.getIdent() + "] " + formViewDef.getName() + "\nThe form will not operate correctly. Please fix it before continuing."); formCell.setIdent(Long.toString((Calendar.getInstance().getTimeInMillis()))); } if (!formCell.getName().equals("this") && controlsByName.get(formCell.getName()) != null) { UIRegistry.showError( "Two controls have the same Name [" + formCell.getName() + "] " + formViewDef.getName()); return; } if (addIt) { builder.add(subView, cc.xywh(colInx, rowInx, colSpan, rowSpan, "fill,fill")); } FVOFieldInfo fi = new FVOFieldInfo(formCell, subView, controlsById.size()); controlsById.put(formCell.getIdent(), fi); controlsByName.put(formCell.getName(), fi); kids.add(subView); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#addSubView(edu.ku.brc.ui.forms.persist.FormCellSubView, edu.ku.brc.ui.forms.MultiView, int, int, int, int) */ public void addSubView(final FormCellSubView formCell, final MultiView subView, final int colInx, final int rowInx, final int colSpan, final int rowSpan) { addSubView(formCell, subView, colInx, rowInx, colSpan, rowSpan, true); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#closeSubView(edu.ku.brc.ui.forms.persist.FormCellSubView) */ public void closeSubView(FormCellSubView formCell) { // not supported } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#shouldFlatten() */ public boolean shouldFlatten() { return false; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ViewBuilderIFace#getControlByName(java.lang.String) */ public Component getControlByName(final String name) { Pair<Component, FormViewObj> result = this.getControlWithFormViewObjByName(name); if (result != null) { return result.getFirst(); } else { return null; } } /** * @param name * @return */ public Pair<Component, FormViewObj> getControlWithFormViewObjByName(final String name) { FVOFieldInfo fieldInfo = controlsByName.get(name); // If it wasn't found in the immediate form then // recurse through all the SubViews if (fieldInfo == null) { for (MultiView mv : kids) { if (mv != null) { FormViewObj fvo = mv.getCurrentViewAsFormViewObj(); if (fvo != null) { Component comp = fvo.getControlByName(name); if (comp != null) { return new Pair<Component, FormViewObj>(comp, fvo); } } } } } else { if (fieldInfo.comp instanceof EditViewCompSwitcherPanel) { return new Pair<Component, FormViewObj>( ((EditViewCompSwitcherPanel) fieldInfo.comp).getCurrentComp(), this); } return new Pair<Component, FormViewObj>(fieldInfo.comp, this); } return null; } /** * Returns the FormViewObj for the control with the name passed in. * @param name the name of the control * @return the FormViewObj that the control with "name" belongs to. */ public FormViewObj getFormViewObjForControlName(final String name) { FVOFieldInfo fieldInfo = controlsByName.get(name); // If it wasn't found in the immediate form then // recurse through all the SubViews if (fieldInfo == null) { for (MultiView mv : kids) { if (mv != null) { FormViewObj fvo = mv.getCurrentViewAsFormViewObj(); if (fvo != null) { Component comp = fvo.getControlByName(name); if (comp != null) { return fvo; } } } } } return null; } /** * If the Control is found and implements UIValidatable it gets set to be changed; * and if it has a DataChangeNotifier then that is also set. * @param controlName the name of the control */ public void setControlChanged(final String controlName) { FVOFieldInfo fieldInfo = controlsByName.get(controlName); Component comp = null; FormViewObj formViewObj = null; // If it wasn't found in the immediate form then // recurse through all the SubViews if (fieldInfo == null) { for (MultiView mv : kids) { if (mv != null) { FormViewObj fvo = mv.getCurrentViewAsFormViewObj(); if (fvo != null) { comp = fvo.getControlByName(controlName); if (comp != null) { formViewObj = fvo; break; } } } } } else { comp = fieldInfo.getComp(); formViewObj = this; } if (comp != null && formViewObj != null) { if (comp instanceof UIValidatable) { ((UIValidatable) comp).setChanged(true); } formViewObj.getValidator().setDataChangeInNotifier(comp); } } /** * @return the rsController */ public ResultSetController getRsController() { return rsController; } /** * @return the businessRules */ public BusinessRulesIFace getBusinessRules() { return businessRules; } /** * This hooks up all the labels so double click bring up the usage notes (the description). */ public void addUsageNotes() { if (tableInfo == null) { tableInfo = DBTableIdMgr.getInstance().getByClassName(formViewDef.getClassName()); } if (tableInfo != null) { for (String idStr : controlsById.keySet()) { FVOFieldInfo fc = controlsById.get(idStr); if (StringUtils.isNotEmpty(fc.getName())) { final DBTableChildIFace tci = tableInfo.getItemByName(fc.getName()); if (tci != null && StringUtils.isNotEmpty(tci.getDescription())) { FVOFieldInfo lbl = labels.get(idStr); if (lbl != null) { lbl.getComp().addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { super.mouseClicked(e); if (e.getClickCount() == 2) { JOptionPane.showMessageDialog(UIRegistry.getMostRecentWindow(), "<html>" + tci.getDescription(), UIRegistry.getResourceString("FormViewObj.UNOTES"), JOptionPane.INFORMATION_MESSAGE); } } }); } } } } } } //----------------------------------------------------- // ValidationListener //----------------------------------------------------- /** * @return the carryFwdInfo */ public CarryForwardInfo getCarryFwdInfo() { return carryFwdInfo; } /** * @return the carryFwdDataObj */ public Object getCarryFwdDataObj() { return carryFwdDataObj; } /* (non-Javadoc) * @see ValidationListener#wasValidated(UIValidator) */ public void wasValidated(final UIValidator validator) { if (formValidator != null) { formValidator.updateValidationBtnUIState(); // The Validator enabled the Delete Btn // Now make sure the Delete Btn should still be enabled /*if (delRecBtn != null && delRecBtn.isEnabled() && dataObj != null && (dataObj instanceof FormDataObjIFace && ((FormDataObjIFace)dataObj).getId() == null)) { log.debug("2----------------- "+formViewDef.getName()+" false----------------- "); //delRecBtn.setEnabled(false); }*/ } } //------------------------------------------------- // ResultSetControllerListener //------------------------------------------------- /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ResultSetControllerListener#indexChanged(int) */ public void indexChanged(int newIndex) { //log.debug("---------------------------------------------------------------------"); //log.debug("Before setDataIntoUI"); //log.debug("Form Val: "+(formValidator != null && formValidator.hasChanged())); //log.debug("mvParent Val: "+(mvParent != null && mvParent.isTopLevel() && mvParent.hasChanged())); if (formValidator != null && formValidator.hasChanged()) { getDataFromUI(); } if (list != null) { if (list.isEmpty()) { return; } Object listDO = list.get(newIndex); if (recordSetItemList != null && listDO == null) { dataObj = getDataObjectViaRecordSet(newIndex); list.remove(newIndex); list.insertElementAt(dataObj, newIndex); } else { dataObj = listDO; // DataProviderSessionIFace tmpSession = DataProviderFactory.getInstance().createSession(); // try // { // tmpSession.attach(dataObj); // ((FormDataObjIFace)dataObj).forceLoad(); // // } catch (Exception ex) // { // ex.printStackTrace(); // edu.ku.brc.af.core.UsageTracker.incrHQLUsageCount(); // edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(FormViewObj.class, ex); // // } finally // { // tmpSession.close(); // } } } ///////////////////////////////////////////////////////////////////////////////// // NOTE: This needs to be here below the setting of the index call because // changing the index will set it to false and we need it to be set // to true when leaving this method. ///////////////////////////////////////////////////////////////////////////////// isNewlyCreatedDataObj = false; // shouldn't be needed, but just in case if (rsController != null) { rsController.setNewObj(isNewlyCreatedDataObj); } if (formValidator != null) { formValidator.setNewObj(isNewlyCreatedDataObj); } //log.debug("Before2 setDataIntoUI"); //log.debug("Form Val: "+(formValidator != null && formValidator.hasChanged())); //log.debug("mvParent Val: "+(mvParent != null && mvParent.isTopLevel() && mvParent.hasChanged())); // rods - 07/22/08 - Trying to force a session to be created. // so child Sets can get lazy loaded. setDataIntoUI(true, true); //log.debug("After setDataIntoUI"); //log.debug("Form Val: "+(formValidator != null && formValidator.hasChanged())); //log.debug("mvParent Val: "+(mvParent != null && mvParent.isTopLevel() && mvParent.hasChanged())); if (saveControl != null) { saveControl.setEnabled(false); } else if (mvParent != null && mvParent.hasChanged()) { Viewable currView = mvParent.getTopLevel().getCurrentView(); if (currView != null && currView.getSaveComponent() != null) { currView.getSaveComponent().setEnabled(false); } } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ResultSetControllerListener#indexAboutToChange(int, int) */ public boolean indexAboutToChange(final int oldIndex, final int newIndex) { return isDataCompleteAndValid(false); /*if (formValidator != null && formValidator.hasChanged()) { getDataFromUI(); } return true; */ } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.ResultSetControllerListener#newRecordAdded() */ public void newRecordAdded() { if (mvParent.getMultiViewParent() != null) { formValidator.setHasChanged(true); formValidator.validateRoot(); } } //------------------------------------------------- // PropertyChangeListener //------------------------------------------------- /* (non-Javadoc) * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent pce) { if (pce != null && StringUtils.isNotEmpty(pce.getPropertyName()) && pce.getPropertyName().equals("data")) { setDataIntoUI(false, false); } } //------------------------------------------------- // AppPrefsChangeListener //------------------------------------------------- protected void setColorOnControls(final int colorType, final Color color) { for (FVOFieldInfo fieldInfo : controlsById.values()) { if (fieldInfo.isOfType(FormCellIFace.CellType.field)) { FormCellFieldIFace cellField = (FormCellFieldIFace) fieldInfo.getFormCell(); FormCellField.FieldType uiType = cellField.getUiType(); //log.debug("["+uiType+"]"); // XXX maybe check check to see if it is a JTextField component instead if (uiType == FormCellFieldIFace.FieldType.dsptextfield || uiType == FormCellFieldIFace.FieldType.dsptextarea) { Component comp = fieldInfo.getComp(); if (colorType == 0) { if (comp instanceof JScrollPane) { ((JScrollPane) comp).getViewport().getView().setBackground(color); } else { fieldInfo.getComp().setBackground(color); } } } } } } /* (non-Javadoc) * @see edu.ku.brc.af.prefs.AppPrefsChangeListener#preferenceChange(edu.ku.brc.af.prefs.AppPrefsChangeEvent) */ public void preferenceChange(AppPrefsChangeEvent evt) { if (evt.getKey().equals("viewfieldcolor")) { ColorWrapper viewFieldColorLocal = AppPrefsCache.getColorWrapper("ui", "formatting", "viewfieldcolor"); setColorOnControls(0, viewFieldColorLocal.getColor()); } //log.debug("Pref: ["+evt.getKey()+"]["+pref.get(evt.getKey(), "XXX")+"]"); } /** * @return returns hash table mapping the Ids to the Names */ public Hashtable<String, String> getIdToNameHash() { Hashtable<String, String> hash = new Hashtable<String, String>(); for (FVOFieldInfo fieldInfo : controlsById.values()) { hash.put(fieldInfo.getId(), fieldInfo.getName()); } return hash; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getFieldIds(java.util.List) */ public void getFieldIds(final List<String> fieldIds) { getFieldIds(fieldIds, false); } /** * @param fieldIds * @param doAll */ public void getFieldIds(final List<String> fieldIds, final boolean doAll) { for (FVOFieldInfo fieldInfo : controlsById.values()) { if (fieldInfo.isOfType(FormCellIFace.CellType.field) || doAll) { fieldIds.add(fieldInfo.getFormCell().getIdent()); } } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.Viewable#getFieldNames(java.util.List) */ public void getFieldNames(final List<String> fieldNames) { ArrayList<FVOFieldInfo> flds = new ArrayList<FVOFieldInfo>(); for (FVOFieldInfo fieldInfo : controlsByName.values()) { if (fieldInfo.isOfType(FormCellIFace.CellType.field)) { flds.add(fieldInfo); } } Collections.sort(flds); for (FVOFieldInfo fieldInfo : flds) { fieldNames.add(fieldInfo.getName()); } } /** * @return the isAlwaysGetDataFromUI */ @Override public boolean isAlwaysGetDataFromUI() { return isAlwaysGetDataFromUI; } /** * @param isAlwaysGetDataFromUI the isAlwaysGetDataFromUI to set */ @Override public void setAlwaysGetDataFromUI(boolean isAlwaysGetDataFromUI) { this.isAlwaysGetDataFromUI = isAlwaysGetDataFromUI; } //------------------------------------------------- // SelectorCellRenderer //------------------------------------------------- public class SelectorCellRenderer extends DefaultListCellRenderer { public SelectorCellRenderer() { super(); } public Component getListCellRendererComponent(@SuppressWarnings("hiding") JList list, Object value, // value to display int index, // cell index boolean iss, // is the cell selected boolean chf) // the list and the cell have the focus { AltViewIFace av = (AltViewIFace) value; JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, iss, chf); label.setText(av.getTitle()); return label; } } //------------------------------------------------- // FieldInfo //------------------------------------------------- public class FVOFieldInfo implements Comparable<FVOFieldInfo> { protected FormCellIFace formCell; protected MultiView subView; protected Component comp; protected JScrollPane fieldScrollPane; protected Integer insertPos; protected UIPluginable uiPlugin; // used by CarryForwardSetup protected String label = null; protected DBInfoBase fieldInfo; public FVOFieldInfo(FormCellIFace formCell, Component comp, JScrollPane scrollPane, int insertPos) { this.comp = comp; this.formCell = formCell; this.subView = null; this.fieldScrollPane = scrollPane; this.insertPos = insertPos; this.uiPlugin = null; } public FVOFieldInfo(FormCellIFace formCell, MultiView subView, int insertPos) { this.formCell = formCell; this.subView = subView; this.comp = subView; this.insertPos = insertPos; this.uiPlugin = null; } public FVOFieldInfo(FormCellIFace formCell, UIPluginable uiPlugin, int insertPos) { this.formCell = formCell; this.subView = null; this.comp = uiPlugin.getUIComponent(); this.insertPos = insertPos; this.uiPlugin = uiPlugin; } /** * @return */ public boolean isRequired() { boolean isRequired = false; if (fieldInfo instanceof DBFieldInfo) { isRequired = ((DBFieldInfo) fieldInfo).isRequired(); } else if (fieldInfo instanceof DBRelationshipInfo) { isRequired = ((DBRelationshipInfo) fieldInfo).isRequired(); } if (!isRequired && comp instanceof UIValidatable) { isRequired = ((UIValidatable) comp).isRequired(); } return isRequired; } public boolean isOfType(final FormCell.CellType type) { return formCell.getType() == type; } public String getName() { return formCell.getName(); } public String getId() { return formCell.getIdent(); } public Component getComp() { return comp; } public FormCellIFace getFormCell() { return formCell; } public MultiView getSubView() { return subView; } public int getInsertPos() { return insertPos; } /** * @return the uiPlugin */ public UIPluginable getUiPlugin() { return uiPlugin; } public void setEnabled(boolean enabled) { //log.debug(formCell.getName()+" "+(scrollPane != null ? "has Pane" : "no pane")); comp.setEnabled(enabled); if (fieldScrollPane != null) { fieldScrollPane.setEnabled(enabled); } } /** * Tells it to clean up */ public void shutdown() { if (comp instanceof UIValidatable) { ((UIValidatable) comp).cleanUp(); } else if (comp instanceof UIPluginable) { ((UIPluginable) comp).shutdown(); } formCell = null; subView = null; comp = null; fieldScrollPane = null; label = null; fieldInfo = null; } /* (non-Javadoc) * @see java.lang.Comparable#compareTo(java.lang.Object) */ public int compareTo(FVOFieldInfo o) { return insertPos.compareTo(o.insertPos); } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } /* (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { return label; } /** * @return the fieldInfo */ public DBInfoBase getFieldInfo() { return fieldInfo; } /** * @param fieldInfo the fieldInfo to set */ public void setFieldInfo(DBInfoBase fieldInfo) { this.fieldInfo = fieldInfo; } } /** * @return the useDebugForm */ public static boolean isUseDebugForm() { return useDebugForm; } /** * @param useDebugForm the useDebugForm to set */ public static void setUseDebugForm(boolean useDebugForm) { FormViewObj.useDebugForm = useDebugForm; } }