edu.ku.brc.af.ui.forms.MultiView.java Source code

Java tutorial

Introduction

Here is the source code for edu.ku.brc.af.ui.forms.MultiView.java

Source

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

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

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

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.db.DBTableChildIFace;
import edu.ku.brc.af.core.db.DBTableIdMgr;
import edu.ku.brc.af.core.db.DBTableInfo;
import edu.ku.brc.af.ui.db.ViewBasedDisplayIFace;
import edu.ku.brc.af.ui.forms.persist.AltViewIFace;
import edu.ku.brc.af.ui.forms.persist.FormCellIFace;
import edu.ku.brc.af.ui.forms.persist.FormCellSubViewIFace;
import edu.ku.brc.af.ui.forms.persist.ViewDefIFace;
import edu.ku.brc.af.ui.forms.persist.ViewIFace;
import edu.ku.brc.af.ui.forms.persist.ViewLoader;
import edu.ku.brc.af.ui.forms.validation.FormValidator;
import edu.ku.brc.dbsupport.DataProviderSessionIFace;
import edu.ku.brc.dbsupport.RecordSetItemIFace;
import edu.ku.brc.ui.CommandAction;
import edu.ku.brc.ui.CommandDispatcher;

/**
 * A MulitView is a "view" that contains multiple Viewable object that can display the current data object in any of the given views.
 * Typically three views are registered: Form, Table, and Field <BR>
 * <BR>
 * Upon creation the agruement "createWithMode" tells the creation mechanism whether to look for and obey the "View" vs "Edit" modeness.
 * Meaning that if we have a view with subview and they (or some of them) have both a n Edit View and a non-Edit View,
 * all the subview will be created as either view or edit form according to the parent's mode.
 *
 * @code_status Beta
 *
 * @author rods
 *
 */
@SuppressWarnings("serial")
public class MultiView extends JPanel {
    // These are the configuration Options for a View
    public static final int NO_OPTIONS = 0; // Indicates there are no options
    public static final int RESULTSET_CONTROLLER = 1; // Add the ResultSet Controller with First,Previous,Next, Last
    public static final int VIEW_SWITCHER = 2; // Add a View Switch in the bottom right
    public static final int IS_NEW_OBJECT = 4; // Indicates the form will contain a brand new data object
    public static final int HIDE_SAVE_BTN = 8; // Hide the Save Button
    public static final int IS_EDITTING = 16; // Whether the MultiView is in Edit mode.
    public static final int IS_SINGLE_OBJ = 32; // Whether the data being passed into the MultiView is a Collection of Object or a single Object
    public static final int NO_SCROLLBARS = 64; // Whether the form should be scrollable
    public static final int ADD_SEARCH_BTN = 128; // Whether a special search btn should be added
    public static final int DONT_ADD_ALL_ALTVIEWS = 256; // Whether it is OK to add all the AltView to the Switcher
    public static final int USE_ONLY_CREATION_MODE = 512; // Create only the AltViews that have the same creation mode
    public static final int DONT_USE_EMBEDDED_SEP = 1024; // use the internal embedded separator
    public static final int NO_MORE_BTN_FOR_SEP = 2048; // doesn't include the separator's 'more' btn
    public static final int COLLAPSE_SEPARATOR = 4096; // Make the Collapse Separator collapsed
    public static final int INCLUDE_ADD_BTN = 8192; // Includes the add btn even if the search btn has been added
    public static final int HIDE_RESULTSET_CONTROLLER = 16384; //Make the ResultSet Controller invisible. 

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

    protected MultiView mvParent = null;
    protected String cellName = null;
    protected ViewIFace view;
    protected Hashtable<String, Viewable> viewMapByName = new Hashtable<String, Viewable>();
    protected Object data = null;
    protected Object parentDataObj = null;
    protected JPanel cardPanel;
    protected CardLayout cardLayout = new CardLayout();
    protected Viewable currentViewable = null;
    protected FormValidator currentValidator = null;
    protected Class<?> classToCreate = null;
    protected FormCellIFace cell = null;

    protected PermissionSettings permissions;

    protected boolean editable = false;
    protected AltViewIFace.CreationMode createWithMode = AltViewIFace.CreationMode.NONE;
    protected boolean ignoreDataChanges = false;
    protected boolean isNewForm = false;

    protected int createOptions = 0;

    protected List<MultiView> kids = new ArrayList<MultiView>();

    protected List<ViewBasedDisplayIFace> displayFrames = null;

    protected boolean isSelectorForm;
    protected String selectorValue = null;
    protected boolean doingSelector = false; // This keeps us from recursing into the selector forever

    protected Vector<Object> deletedItems = null;
    protected Vector<Object> toBeSavedItems = null;

    protected CollapsableSeparator separator = null;

    /**
     * Constructor - Note that createWithMode can be null and is passed in from parent ALWAYS.
     * So forms that may not have multiple views or do not wish to have Edit/View can pass in null. (See Class description)
     * @param mvParent parent of this MultiView the root MultiView is null
     * @param view the view to create for
     * @param createWithMode how the form should be created (None, Edit or View mode)
     * @param options the options needed for creating the form
     */
    public MultiView(final MultiView mvParent, final String cellName, final ViewIFace view,
            final AltViewIFace.CreationMode createWithMode, final int options) {
        this(mvParent, cellName, view, createWithMode, null, options, null, null);
    }

    /**
     * Constructor - Note that createWithMode can be null and is passed in from parent ALWAYS.
     * So forms that may not have multiple views or do not wish to have Edit/View can pass in null. (See Class description)
     * @param mvParent parent of this MultiView the root MultiView is null
     * @param view the view to create for
     * @param createWithMode how the form should be created (Noe, Edit or View mode)
     * @param options the options needed for creating the form
     * @param bgColor background color
     */
    public MultiView(final MultiView mvParent, final String cellName, final ViewIFace view,
            final AltViewIFace.CreationMode createWithMode, final int options, final Color bgColor) {
        this(mvParent, cellName, view, createWithMode, null, options, bgColor, null);
    }

    /**
     * Constructor - Note that createWithMode can be null and is passed in from parent ALWAYS.
     * So forms that may not have multiple views or do not wish to have Edit/View can pass in null. (See Class description)
     * @param mvParent parent of this MultiView the root MultiView is null
     * @param view the view to create for
     * @param createWithMode how the form should be created (None, Edit or View mode)
     * @param defaultAltViewType suggestion as to whether to use a form or a grid
     * @param options the options needed for creating the form
     */
    public MultiView(final MultiView mvParent, final String cellName, final ViewIFace view,
            final AltViewIFace.CreationMode createWithMode, final String defaultAltViewType, final int options) {
        this(mvParent, cellName, view, createWithMode, defaultAltViewType, options, null, null);
    }

    /**
     * Constructor - Note that createWithMode can be null and is passed in from parent ALWAYS.
     * So forms that may not have multiple views or do not wish to have Edit/View can pass in null. (See Class description)
     * @param mvParent parent of this MultiView the root MultiView is null
     * @param view the view to create for
     * @param createWithMode how the form should be created (None, Edit or View mode)
     * @param defaultAltViewType suggestion as to whether to use a form or a grid
     * @param options the options needed for creating the form
     * @param bgColor background color
     * @param cell  the definition of the MultiView when it is a subview
     */
    public MultiView(final MultiView mvParent, final String cellName, final ViewIFace view,
            final AltViewIFace.CreationMode createWithMode, final String defaultAltViewType, final int options,
            final Color bgColor, final FormCellIFace cell) {
        this.mvParent = mvParent;
        this.cellName = cellName;
        this.view = view;
        this.createWithMode = createWithMode;
        this.createOptions = options | (createWithMode == AltViewIFace.CreationMode.EDIT ? IS_EDITTING : 0);
        this.cell = cell;

        String title = cell != null ? cell.getProperty("title") : null;
        initializeCardPanel(options, title);

        this.isSelectorForm = StringUtils.isNotEmpty(view.getSelectorName());

        if (bgColor != null) {
            setBackground(bgColor);
        }

        boolean isUsingSwitcher = MultiView.isOptionOn(createOptions, MultiView.VIEW_SWITCHER);
        boolean isUsingOnlyCreationMode = MultiView.isOptionOn(createOptions, MultiView.USE_ONLY_CREATION_MODE);
        boolean isUsingSelector = StringUtils.isNotEmpty(view.getSelectorName());

        //log.debug("isUsingOnlyCreationMode "+isUsingOnlyCreationMode + " " + createWithMode + "  defaultAltViewType: "+defaultAltViewType);

        if (mvParent == null && ViewLoader.isDoFieldVerification()) {
            ViewLoader.clearFieldVerInfo();
        }

        if (AppContextMgr.isSecurityOn()) {
            this.permissions = getPremissionFromView(view, getClassNameFromParentMV(null, mvParent, cellName));
            //PermissionSettings.dumpPermissions("DO."+view.getName(), permissions.getOptions());
        } else {
            this.permissions = new PermissionSettings(PermissionSettings.ALL_PERM);
        }

        AltViewIFace defaultAltView = createDefaultViewable(defaultAltViewType);

        if (isUsingSwitcher) {
            for (AltViewIFace av : view.getAltViews()) {
                if ((isUsingOnlyCreationMode && av.getMode() == createWithMode)
                        || (!isUsingOnlyCreationMode && (av.getMode() == createWithMode || mvParent == null))) {
                    // temporarily set this for creation, because it gets asked via getMode()
                    this.createWithMode = av.getMode();

                    //log.debug("CREATING: createWithMode "+createWithMode+"  "+av.getName()+" "+av.getMode());
                    createViewable(av.getName(), cellName);

                } else {
                    //log.debug("SKIPPED:  createWithMode "+createWithMode+"  "+av.getName()+" "+av.getMode());
                }
            }
        } else if (isUsingSelector && defaultAltView.getMode() == AltViewIFace.CreationMode.EDIT) // Special situation for selectors in edit mode
        {
            for (AltViewIFace av : view.getAltViews()) {
                if (av.getMode() == createWithMode && av.getMode() == AltViewIFace.CreationMode.EDIT) {
                    // temporarily set this for creation, because it gets asked via getMode()
                    this.createWithMode = av.getMode();

                    //log.debug("CREATING: createWithMode "+createWithMode+"  "+av.getName()+" "+av.getMode());
                    createViewable(av.getName(), cellName);
                }
            }
        } else {
            createViewable(defaultAltView.getName(), cellName);
        }

        this.createWithMode = createWithMode;

        editable = defaultAltView.getMode() == AltViewIFace.CreationMode.EDIT;

        showView(defaultAltView.getName());

        //log.debug( "*** Parent " + (mvParent != null ? "NOT NULL" : "NULL"));
        if (currentViewable != null) {
            currentValidator = currentViewable.getValidator();
        }

        if (mvParent == null && ViewLoader.isDoFieldVerification()) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    ViewLoader.displayFieldVerInfo();
                }
            });

        }
    }

    /**
     * Constructor - Note that createWithMode can be null and is passed in from parent ALWAYS.
     * So forms that may not have multiple views or do not wish to have Edit/View can pass in null. (See Class description)
     * @param mvParent parent of this MultiView the root MultiView is null
     * @param view the view to create for
     * @param createWithMode how the form should be created (Noe, Edit or View mode)
     * @param options the options needed for creating the form
     */
    public MultiView(final MultiView mvParent, final String cellName, final ViewIFace view,
            final AltViewIFace altView, final AltViewIFace.CreationMode createWithMode, final int options) {
        this.mvParent = mvParent;
        this.cellName = cellName;
        this.view = view;
        this.createWithMode = createWithMode;
        this.createOptions = options
                | (createWithMode == AltViewIFace.CreationMode.EDIT ? IS_EDITTING : NO_OPTIONS);

        initializeCardPanel(options, null);

        if (AppContextMgr.isSecurityOn()) {
            this.permissions = getPremissionFromView(view, getClassNameFromParentMV(null, mvParent, cellName));
        } else {
            this.permissions = new PermissionSettings(PermissionSettings.ALL_PERM);
        }

        AltViewIFace avi = altView != null ? altView : createDefaultViewable(null);
        createViewable(avi, cellName);
        showView(avi.getName());
    }

    /**
     * @param options
     */
    private void initializeCardPanel(final int options, final String title) {
        if (!isOptionOn(options, DONT_USE_EMBEDDED_SEP)) {
            setLayout(new BorderLayout());

            String titleStr = view.getTitle();
            if (StringUtils.isNotEmpty(title)) {
                titleStr = title;

            } else if (mvParent != null && StringUtils.isNotEmpty(cellName)) {
                DBTableInfo parentTblInfo = DBTableIdMgr.getInstance()
                        .getByClassName(mvParent.getView().getClassName());
                if (parentTblInfo != null) {
                    DBTableChildIFace childInfo = parentTblInfo.getItemByName(cellName);
                    if (childInfo != null) {
                        titleStr = childInfo.getTitle();
                    }
                }
            }
            this.cardPanel = new JPanel(cardLayout);
            this.cardPanel.setVisible(!isOptionOn(options, COLLAPSE_SEPARATOR));

            JComponent extraComp = CollapsableSepExtraCompFactory.getInstance().getComponent("Form",
                    view.getClassName());
            this.separator = new CollapsableSeparator(titleStr, !isOptionOn(options, NO_MORE_BTN_FOR_SEP),
                    extraComp);
            this.separator.setInnerComp(this.cardPanel);
            this.cardPanel.setOpaque(false);

            add(this.separator, BorderLayout.NORTH);
            add(this.cardPanel, BorderLayout.CENTER);

        } else {
            setLayout(cardLayout);
        }
    }

    /**
     * @return the cellName
     */
    public String getCellName() {
        return cellName;
    }

    /**
     * Get the short class name for the cell's data type.
     * @param dataClass the class of the data that is put into the form
     * @param parent the MultiView parent
     * @param cellName the cell name of the child
     * @return the short class name for the class type of the data for the cell
     */
    public static String getClassNameFromParentMV(final Class<?> dataClass, final MultiView parent,
            final String cellName) {
        String dataClassName = dataClass != null ? dataClass.getSimpleName() : null;
        if (dataClassName == null && parent != null && cellName != null) {
            String className = parent.getView().getClassName();
            if (className != null) {
                DBTableInfo tblInfo = DBTableIdMgr.getInstance().getByClassName(className);
                if (tblInfo != null) {
                    DBTableChildIFace childInfo = tblInfo.getItemByName(cellName);
                    if (childInfo != null) {
                        dataClassName = childInfo.getDataClass().getSimpleName();
                    } else {
                        log.debug("Couldn't find cellName[" + cellName + "] for table[" + tblInfo.getName() + "]");
                    }
                }
            }
        }
        return dataClassName;
    }

    /**
     * Get the Permissions for the data type from the views.
     * @param view the view
     * @param shortClassName the short class name if it is already know (null can be passed in)
     * @return the permissions
     */
    public static PermissionSettings getPremissionFromView(final ViewIFace view, final String shortClassName) {
        String shortClass = StringUtils.isNotEmpty(shortClassName) ? shortClassName
                : StringUtils.substringAfterLast(view.getClassName(), ".");
        if (shortClass == null) {
            shortClass = view.getClassName();
        }
        return SecurityMgr.getInstance().getPermission("DO." + shortClass.toLowerCase());
    }

    /**
     * @return the permissions
     */
    public PermissionSettings getPermissions() {
        return permissions;
    }

    /**
     * @return the separator
     */
    public CollapsableSeparator getSeparator() {
        return separator;
    }

    /**
     * Sometimes the caller may wish to have the form validated after being initialized. 
     */
    public void preValidate() {
        FormViewObj formViewObj = getCurrentViewAsFormViewObj();
        if (formViewObj != null) {
            formViewObj.getValidator().setHasChanged(true);
            formViewObj.getValidator().wasValidated(null);
        }
    }

    /**
     * @return
     */
    public FormValidator getCurrentValidator() {
        if (currentViewable != null) {
            return currentViewable.getValidator();
        }
        return null;
    }

    /**
     * @return the form's first focusable object.
     */
    public Component getFirstFocusable() {
        FormViewObj formView = getCurrentViewAsFormViewObj();
        if (formView != null) {
            return formView.getFirstFocusable();
        }
        return null;
    }

    /**
     * Returns a Collection of the Viewables
     * @return  a Collection of the Viewables
     */
    public Collection<Viewable> getViewables() {
        return viewMapByName.values();
    }

    /**
     * Asks the Viewable to get the data from the UI and transfer the changes (really all the fields) to
     * the DB object.
     */
    public void getDataFromUI() {
        for (Enumeration<Viewable> e = viewMapByName.elements(); e.hasMoreElements();) {
            Viewable viewable = e.nextElement();
            if (viewable.isAlwaysGetDataFromUI()
                    || (viewable.getValidator() != null && viewable.getValidator().hasChanged())) // XXX Not sure why it must have a validator ???
            {
                viewable.getDataFromUI();
                //if (viewable.getValidator() != null && viewable.getValidator().hasChanged())
                //{
                //if (FormHelper.updateLastEdittedInfo(viewable.getDataObj()))
                //{
                //    viewable.setDataIntoUI();
                //}
                //}
            }
            // XXX For the Demo I can't figure out why a Different session is being checked when I try
            // to save the session in the form.
            if (viewable instanceof RecordSetTableViewObj) {
                viewable.getDataFromUI();
            }
        }
    }

    /**
     * Asks the first component to be focused. 
     */
    public void focus() {
        if (currentViewable != null) {
            currentViewable.focus();
        }
    }

    /**
     * Asks the immediate SubViews to create data (via the Business Rules).
     */
    public void initSubViews() {
        FormViewObj fvo = getCurrentViewAsFormViewObj();
        if (fvo != null) {
            fvo.initSubViews();
        }
    }

    /**
     * Returns the View (the definition).
     * @return the View (the definition)
     */
    public ViewIFace getView() {
        return view;
    }

    /**
     * Returns all the Multiview children.
     * @return all the Multiview children
     */
    public List<MultiView> getKids() {
        return kids;
    }

    /**
     * The flags used when the MultiView was created.
     * @return the int bit mask of options
     */
    public int getOptions() {
        return createOptions;
    }

    /**
     * Called to tell current view it is about to be shown or hidden.
     * @param show true - shown, false - hidden
     */
    public void aboutToShow(final boolean show) {
        if (currentViewable != null) {
            currentViewable.aboutToShow(show);
        }
        showDisplayFrames(show);
    }

    /**
     * @return
     */
    public boolean isNewForm() {
        return isNewForm;
    }

    /**
     * Tells all the Viewables that have validators that the form is new or old.
     * NOTE: New Forms means that it is an empty form and that the controls should
     * not show validation errors until they have had focus if they are a validator that changes on input
     * and not by the OK button or by focus.
     * @param isNewForm whether the form is handling a new obj
     * @param traverseKids whether the MultiView should traverse into the children MultiViews
     */
    public void setIsNewForm(final boolean isNewForm, final boolean traverseKids) {
        this.isNewForm = isNewForm;

        for (Enumeration<Viewable> e = viewMapByName.elements(); e.hasMoreElements();) {
            Viewable viewable = e.nextElement();
            if (viewable.getValidator() != null) {
                FormValidator fv = viewable.getValidator();
                fv.setUIValidatorsToNew(isNewForm);
                // rods 09/24/08 added the if statement because all the validators 
                // in the immediate subforms were being set to not be changed
                if (!isNewForm) {
                    fv.setUIValidatorsToNotChanged();
                }
                viewable.setHasNewData(isNewForm);
            }
        }

        if (traverseKids) {
            for (MultiView mv : kids) {
                mv.setIsNewForm(isNewForm, traverseKids);
            }
        }
    }

    /**
     * Sets all validators to unchanged state.
     */
    public void clearValidators() {
        if (currentValidator != null) {
            currentValidator.setUIValidatorsToNotChanged();
        }
    }

    /**
     * Returns true if any of the validators have changed, false if it has no validators or they haven't changed.
     * @return true if any of the validators have changed, false if it has no validators or they haven't changed.
     */
    public boolean hasChanged() {
        if (!ignoreDataChanges) {
            if (currentValidator != null) {
                //currentValidator.setFirstTime(false);

                if (currentValidator.hasChanged()) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Returns whether this is the top level MultiView, which usually means this is the most outer form.
     * @return whether this is the top level MultiView, which usually means this is the most outer form.
     */
    public boolean isTopLevel() {
        return mvParent == null;
    }

    /**
     * Returns the Top MultiView.
     * @return the Top MultiView.
     */
    public MultiView getTopLevel() {
        if (mvParent == null) {
            return this;
        }
        MultiView top = mvParent;
        while (top != null && top.getMultiViewParent() != null) {
            top = top.mvParent;
        }
        return top;
    }

    /**
     * Creates the Default Viewable for this view (it chooses the "default" ViewDef.
     * @param defAltViewType should contain values: null, grid, form
     * @return return the default Viewable (ViewDef)
     */
    protected AltViewIFace createDefaultViewable(final String defAltViewType) {
        AltViewIFace altView;
        if (createWithMode != null) {
            altView = view.getDefaultAltViewWithMode(createWithMode, defAltViewType);

        } else {
            altView = view.getDefaultAltView(createWithMode, defAltViewType);
        }
        return altView;
    }

    /**
     * Returns the name of the view for the MultiView.
     * @return the name of the view for the MultiView
     */
    public String getViewName() {
        return view.getName();
    }

    /**
     * Adds a viewable to the MultiView.
     * @param viewable the Viewable to be added
     * @param name the name of the view to be added
     * @return true if it was added, false if name conflicts
     */
    protected boolean add(final Viewable viewable, final String name) {
        if (viewMapByName.get(name) != null) {
            log.error("Adding a Viewable by a name that is already used[" + name + "]");
            return false;

        }
        // else
        viewable.setCellName(cellName);
        viewMapByName.put(name, viewable);

        // CallapsablePanel
        if (separator != null) {
            cardPanel.add(viewable.getUIComponent(), name);

            JComponent controllerPanel = viewable.getControllerPanel();
            if (controllerPanel == null) {
                controllerPanel = new JPanel();
                controllerPanel.setPreferredSize(new Dimension(0, 0));
            }
            separator.addToSubPanel(controllerPanel, name);

        } else {
            add(viewable.getUIComponent(), name);
        }
        return true;
    }

    /**
     * @param fvo
     * @param tableInfo
     * @param recordSetItemList
     */
    public void setRecordSetItemList(final FormViewObj fvo, final DBTableInfo tableInfo,
            final List<RecordSetItemIFace> recordSetItemList) {
        for (Viewable viewable : viewMapByName.values()) {
            if (viewable != fvo && viewable instanceof FormViewObj) {
                ((FormViewObj) viewable).setRecordSetItemList(tableInfo, recordSetItemList);
            }
        }
    }

    /**
     * Show the AltViewIFace.
     * @param altView show the AltViewIFace
     */
    public void showView(final AltViewIFace altView) {
        if (hasChanged()) {
            if (currentViewable != null && currentViewable.isDataCompleteAndValid(false)) {
                showView(altView.getName());
            }
        } else {
            showView(altView.getName());
        }
    }

    /**
     * Show a Viewable by name.
     * @param name the registered name of the component (In this case it is the name of the Viewable)
     */
    public void showView(final String name) {
        Viewable viewable = viewMapByName.get(name);
        if (viewable == null) {
            viewable = createViewable(name, null);
        }

        Vector<ViewState> viewStateList = null;

        /* XXX bug #9497:
        boolean userCanModify = true;
        if (AppContextMgr.isSecurityOn())
        {
           DBTableInfo tableInfo = DBTableIdMgr.getInstance().getByClassName(getView().getClassName());
           if (tableInfo != null && tableInfo.getPermissions() != null) {
          userCanModify = tableInfo.getPermissions().canModify();
           }
        } */
        if (viewable != null) {
            if (currentViewable != null) {
                FormViewObj fvo = getCurrentViewAsFormViewObj();
                if (fvo != null) {
                    viewStateList = fvo.collectionViewState();
                }

                currentViewable.aboutToShow(false);
                //XXX bug #9497: if (currentViewable.getAltView().getMode() == AltViewIFace.CreationMode.EDIT && userCanModify)
                if (currentViewable.getAltView().getMode() == AltViewIFace.CreationMode.EDIT) {
                    currentViewable.getDataFromUI();
                }

                if (currentValidator != null) {
                    adjustValidationTree(this, currentValidator, false);
                }
            }

            currentViewable = viewable;
            currentViewable.aboutToShow(true);

            currentViewable.setParentDataObj(parentDataObj);
            currentValidator = currentViewable.getValidator();

            //XXX bug #9497: createWithMode = userCanModify ? currentViewable.getAltView().getMode() : AltViewIFace.CreationMode.VIEW;
            createWithMode = currentViewable.getAltView().getMode();
            editable = createWithMode == AltViewIFace.CreationMode.EDIT;
            /* XXX bug #9497:
            //don't switch views if userpermissions are not consistent with the requested view
            //if (currentViewable.getAltView().getMode() == AltViewIFace.CreationMode.EDIT && userCanModify) { */
            setData(data, false);

            setFormForSelector();

            if (viewStateList != null) {
                FormViewObj fvo = getCurrentViewAsFormViewObj();
                if (fvo != null) {
                    setViewState(viewStateList, createWithMode, 0);
                }
            }

            if (separator != null) {
                cardLayout.show(cardPanel, name);
                separator.showSubPanel(name);

            } else {
                cardLayout.show(this, name);
            }

            if (currentValidator != null) {
                if (mvParent != null && mvParent.getCurrentValidator() != null) {
                    adjustValidationTree(mvParent, mvParent.getCurrentValidator(), true);
                    //mvParent.getCurrentValidator().dumpState(true, 0);

                } else {
                    adjustValidationTree(this, currentValidator, true);
                    //currentValidator.dumpState(true, 0);
                }
            }

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    CommandDispatcher.dispatch(new CommandAction("Data_Entry", "ViewWasShown", currentViewable));
                }
            });
            if (currentViewable instanceof FormViewObj && !editable) {
                ((FormViewObj) currentViewable).setFormEnabled(false);
            }
            //XXX bug #9497: }

        } else {
            log.error("Viewable was null and shouldn't have been!");
        }
    }

    /**
     *  Create the Viewable from an AltView Name.
     * @param altViewName the name of the AltView
     * @param cellNameArg
     * @return
     */
    public Viewable createViewable(final String altViewName, final String cellNameArg) {
        // Find the AltView to create
        List<AltViewIFace> list = view.getAltViews();
        int inx = 0;
        for (AltViewIFace altView : list) {
            if (altViewName.equals(altView.getName())) {
                return createViewable(altView, cellNameArg);
            }
            inx++;
        }

        log.error("Couldn't find Alt View [" + altViewName + "]in AltViewIFace List");

        return null;
    }

    /**
     * Create the Viewable from an AltView.
     * @param altView the actual AltView object
     * @param cellNameArg
     * @return the viewable for the altview
     */
    protected Viewable createViewable(final AltViewIFace altView, final String cellNameArg) {
        ViewIFace newView = AppContextMgr.getInstance().getView(view.getViewSetName(), altView.getView().getName());
        // 12/14/07 - rods
        // Commented out the line above, I can't figure out why we need to go get a new copy of the View
        // each time this is called
        //ViewIFace newView = view;
        if (newView != null) {
            /*if (false)
            {
            log.debug("--------------------------");
            for (int i=0;i<getComponentCount();i++)
            {
                Component comp = getComponent(i);
                if (comp instanceof Viewable)
                {
                    log.debug(((Viewable)comp).getName());
                } else
                {
                    log.debug(comp);
                }
            }
            log.debug("--------------------------");
            }*/

            int tmpCreateOptions = createOptions
                    | (createWithMode == AltViewIFace.CreationMode.EDIT ? (IS_EDITTING) : 0);
            //MultiView.printCreateOptions("createViewable: "+altView.getName(), createOptions);
            Viewable viewable = ViewFactory.createFormView(this, newView, altView.getName(), data, tmpCreateOptions,
                    cellNameArg, getBackground());
            if (viewable != null) {
                if (add(viewable, altView.getName())) {
                    if (viewable instanceof TableViewObj && cell instanceof FormCellSubViewIFace) {
                        ((TableViewObj) viewable).setVisibleRowCount(((FormCellSubViewIFace) cell).getTableRows());
                    }

                    if (mvParent != null) {
                        viewable.getUIComponent().validate();
                        viewable.getUIComponent().doLayout();
                    }

                    //log.debug("Added Viewable["+altView.getName()+"]");

                    validate();
                    invalidate();
                    doLayout();

                    return viewable;
                }

            } else {
                log.error("The Viewable could not be created for some reason View[" + newView + "] AltViewIFace["
                        + altView.getName() + "] Options[" + createOptions + "]");
            }

        } else {
            log.error("Unable to load form ViewSetName [" + currentViewable.getView().getViewSetName() + "] Name["
                    + altView.getName() + "]");
        }

        return null;
    }

    /**
     * @param parent
     * @param parentVal
     * @param doAdd
     */
    protected void adjustValidationTree(final MultiView parent, final FormValidator parentVal,
            final boolean doAdd) {
        parentVal.clearKids();

        if (parent != null) {
            for (MultiView kid : parent.kids) {
                //log.debug(kid.getView().getName()+" "+ kid.getCurrentView().getAltView().getName());

                FormValidator kidVal = kid.getCurrentValidator();
                if (kidVal != null) {
                    if (doAdd) {
                        parentVal.add(kid.getCurrentValidator());
                        kidVal.setParent(parentVal);
                    } /* else
                      {
                      parentVal.remove(kid.getCurrentValidator());
                      kidVal.setParent(null);
                      //                }*/
                    adjustValidationTree(kid, kidVal, doAdd);
                }
            }
        }
    }

    /**
     * 
     */
    protected void addCurrentValidator() {
        if (currentViewable != null) {
            currentValidator = currentViewable.getValidator();
            if (currentValidator != null) {
                if (mvParent != null) {
                    FormValidator parentVal = mvParent.getCurrentValidator();
                    if (parentVal != null) {
                        parentVal.add(currentValidator);
                        currentValidator.setParent(parentVal);
                        //parentVal.dumpState(true, 0);
                    }
                    adjustValidationTree(this, currentValidator, true);

                }
                //currentValidator.dumpState(true, 100);
            }
        } else {
            log.error("CurrentViewable can't be null");
        }
    }

    /**
     * 
     */
    protected void removeCurrentValidator() {
        if (currentValidator != null) {
            adjustValidationTree(mvParent, currentValidator, false);

            FormValidator parentVal = currentValidator.getParent();
            if (parentVal != null) {
                parentVal.remove(currentValidator);
            }
            currentValidator.setParent(null);
            // rods - 7/3/08 - Setting this to null is very bad
            // it clears an existing validator when called from ViewBtn
            //currentValidator = null;
        }
    }

    /**
     * Returns the MultiView's mvParent.
     * @return the MultiView's mvParent
     */
    public MultiView getMultiViewParent() {
        return mvParent;
    }

    /**
     * Sets the parent MV.
     * @param parent the parent MV
     */
    public void setMultiViewParent(final MultiView parent) {
        mvParent = parent;
    }

    /**
     * Adds a MultiView as a child of another MultiView
     * @param kidMV the child to be added
     */
    public void addChildMV(final MultiView kidMV) {
        kids.add(kidMV);
        kidMV.setMultiViewParent(this);
    }

    /**
     * Removes a MultiView as a child of another MultiView
     * @param kidMV the child to be removed
     */
    public void removeChildMV(final MultiView kidMV) {
        kids.remove(kidMV);
        kidMV.setMultiViewParent(null);
    }

    /**
     * Return whether the MultiView is in Edit Mode.
     * @return whether the MultiView is in Edit Mode
     */
    public boolean isEditable() {
        return editable;
    }

    /**
     * Return whether the MultiView's CreateMode (may be null, true or false) meaning don't assume it will always be non-null.
     * @return whether the MultiView's CreateMode (may be null, true or false)
     */
    public AltViewIFace.CreationMode getCreateWithMode() {
        return createWithMode;
    }

    /**
     * @param dObj
     */
    public void setDataIntoParent(final Object dObj) {
        this.data = dObj;
    }

    /**
     * Sets the Data Object into the View.
     * @param data the data object
     */
    public void setData(final Object data) {
        setData(data, true);
    }

    /**
     * Called only by FormViewObj after a save.
     * @param dObj the new data object when it isn't a collection.
     */
    protected void setJustDataObj(final Object dObj) {
        this.data = dObj;
    }

    /**
     * Sets the Data Object into the View.
     * @param data the data object
     */
    protected void setData(final Object data, final boolean doSelector) {
        // If this happens it is because there was a major error elsewhere.
        if (currentViewable == null) {
            return;
        }

        for (Viewable v : viewMapByName.values()) {
            v.enableMultiViewSwitch(false);
        }

        this.data = data;

        ignoreDataChanges = true;

        boolean doSetData = true;
        if (doSelector) {
            doSetData = setFormForSelector();
        }

        if (doSetData) {
            currentViewable.setDataObj(data);
        }

        if (isTopLevel() && currentViewable != null) {
            currentViewable.updateSaveBtn();
        }

        if (isTopLevel()) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    if (currentViewable != null) {
                        currentViewable.focus();
                    }
                }
            });
        }

        for (Viewable v : viewMapByName.values()) {
            v.enableMultiViewSwitch(true);
        }

        ignoreDataChanges = false;

    }

    /**
     * @return
     */
    protected boolean setFormForSelector() {
        if (doingSelector) {
            return true;
        }

        doingSelector = true;

        boolean doSetData = true;

        boolean cacheIgnoreDataChanges = ignoreDataChanges;
        ignoreDataChanges = true;

        selectorValue = null;
        if (isSelectorForm) {
            // We the data gets set into the MultiView we need to display the correct
            // AlView with the matching selector value.
            AltViewIFace altView = currentViewable.getAltView();

            // Set the data into the Current view even though this may not be the correct AltViewIFace
            currentViewable.setDataObj(data);

            String selectorName = altView.getSelectorName();
            DataObjectGettable getter = currentViewable.getViewDef().getDataGettable();
            Object selectorDataVal = getter.getFieldValue(currentViewable.getDataObj(), selectorName);

            if (selectorDataVal != null) {
                String newSelectorValue = selectorDataVal.toString(); // all selector value must be "directly" convertable to string

                // Make the Selector value has changed.
                if (selectorValue == null || !selectorValue.equals(newSelectorValue)) {
                    selectorValue = newSelectorValue;

                    // Find the matching Viewable with the same selectorValue
                    for (AltViewIFace av : view.getAltViews()) {
                        //log.debug("["+av.getSelectorName()+"]["+av.getSelectorValue()+"]["+selectorValue+"]");

                        if (StringUtils.isNotEmpty(av.getSelectorName())
                                && av.getSelectorValue().equals(selectorValue)
                                && altView.getMode() == av.getMode()) {
                            // Save off the current to see if it changes
                            Viewable oldViewable = currentViewable;

                            showView(av.getName());

                            // Now set the data into the "new" viewable if it changed Viewables
                            if (oldViewable != currentViewable) {
                                currentViewable.setDataObj(data);
                                doSetData = false;
                            }
                            break;
                        }
                    }
                }
            } else {
                //AltViewIFace defAltView = view.getDefaultAltViewWithMode(createWithMode, "form");
                //log.debug(defAltView.getName());
                //showView(defAltView.getName());
            }
        }

        ignoreDataChanges = cacheIgnoreDataChanges;
        doingSelector = false;

        return doSetData;

    }

    /**
     * Returns  the data object for this form.
     * @return the data object for this form
     */
    public Object getData() {
        if (data instanceof Collection<?>) {
            return currentViewable.getDataObj();
        }
        return data;
    }

    /**
     * Returns whether all the validation of this form and child forms is OK.
     * @return whether all the validation of this form and child forms is OK
     */
    public boolean isAllValidationOK() {
        if (currentValidator != null) {
            currentValidator.isFormValid();
        }
        return true;
    }

    /**
     * Validates all the forms and subforms.
     */
    public void validateAll() {
        if (currentValidator != null) {
            currentValidator.validateForm();
        }
    }

    /**
     * Sets the dataObj of the parent, this is need to add new child node from subforms.
     * @param parentDataObj the dataObj of the parent
     */
    public void setParentDataObj(Object parentDataObj) {
        this.parentDataObj = parentDataObj;

        //if (currentViewable != null)
        //{
        //currentViewable.setParentDataObj(parentDataObj);
        //}

        for (Viewable v : viewMapByName.values()) {
            v.setParentDataObj(parentDataObj);
        }

        for (MultiView kidMV : kids) {
            kidMV.setParentDataObj(parentDataObj);
        }
    }

    /**
     * Sets into the multiview and viewables the class name that should be used
     * o create new data objects.
     * @param classToCreateArg the class to be created
     */
    public void setClassToCreate(final Class<?> classToCreateArg) {
        this.classToCreate = classToCreateArg;
        for (Viewable v : viewMapByName.values()) {
            v.setClassToCreate(classToCreate);
        }
    }

    /**
     * Returns the dataObj of of the parent.
     * @return the dataObj of of the parent
     */
    public Object getParentDataObj() {
        return parentDataObj;
    }

    /**
     * Registers "display" window for display "sub object" information.
     * @param frame the frame to be added
     */
    public void registerDisplayFrame(final ViewBasedDisplayIFace frame) {
        if (frame != null) {
            if (displayFrames == null) {
                displayFrames = new ArrayList<ViewBasedDisplayIFace>();
            }
            displayFrames.add(frame);
        } else {
            log.error("Registering a null frame!");
        }
    }

    /**
     * Unregsters a frame from the MultiView list of sub-frames.
     * @param frame the frame to be unregistered (removed)
     */
    public void unregisterDisplayFrame(final ViewBasedDisplayIFace frame) {
        if (displayFrames != null) {
            displayFrames.remove(frame);
        }

    }

    /**
     * Shows or hides all the DisplayFrame attached to this MultiView.
     * @param show true - show, false - hide
     */
    public void showDisplayFrames(final boolean show) {
        if (displayFrames != null) {
            for (ViewBasedDisplayIFace frame : displayFrames) {
                frame.showDisplay(show);
            }
        }
    }

    /**
     * Returns the current view.
     * @return the current view
     */
    public Viewable getCurrentView() {
        return currentViewable;
    }

    /**
     * Returns the current viewable as a FormViewObj if it is one, or return null.
     * @return the current viewable as a FormViewObj if it is one, or return null.
     */
    public FormViewObj getCurrentViewAsFormViewObj() {
        return currentViewable instanceof FormViewObj ? (FormViewObj) currentViewable : null;
    }

    /**
     * Returns the options that it was created with.
     * @return the options that it was created with.
     */
    public int getCreateOptions() {
        return createOptions;
    }

    /**
     * @return the isOKToAddAllAltViews
     */
    public boolean isOKToAddAllAltViews() {
        if (AppContextMgr.isSecurityOn() && permissions.isViewOnly()) {
            return false;
        }

        return !MultiView.isOptionOn(createOptions, MultiView.DONT_ADD_ALL_ALTVIEWS);
    }

    /**
     * Adds an item to be deleted to a list.
     * @param deletedItem the item to be deleted.
     */
    public void addDeletedItem(final Object deletedItem) {
        if (deletedItems == null) {
            deletedItems = new Vector<Object>();
        }
        boolean addToList = true;
        if ((deletedItem instanceof Vector<?>)) {
            addToList = false;
        }
        if (addToList) {
            deletedItems.add(deletedItem);
        }
    }

    /**
     * Adds an item to be saved to a list.
     * @param toBeSavedItem the item to be saved.
     */
    public void addToBeSavedItem(final Object toBeSavedItem) {
        if (toBeSavedItems == null) {
            toBeSavedItems = new Vector<Object>();
        }

        boolean addToList = true;
        if (!(toBeSavedItem instanceof FormDataObjIFace))// && ((FormDataObjIFace)toBeSavedItem).getId() == null)
        {
            addToList = false;
        }
        if (addToList) {
            toBeSavedItems.add(toBeSavedItem);
        }
    }

    /**
     * Returns a list of items to be deleted, it may return null.
     * @return a list of items to be deleted, it may return null.
     */
    public Vector<Object> getDeletedItems() {
        return deletedItems;
    }

    /**
     * @return
     */
    public Vector<Object> getToBeSavedItems() {
        return toBeSavedItems;
    }

    /**
     * Clears the list.
     */
    public void clearItemsToBeSaved() {
        if (toBeSavedItems != null) {
            toBeSavedItems.clear();
        }
    }

    /**
     * Clears the list.
     */
    public void clearItemsToBeDeleted() {
        if (deletedItems != null) {
            deletedItems.clear();
        }
    }

    /**
     * Asks the Viewable to get the data from the UI and transfer the changes (really all the fields) to
     * the DB object.
     */
    public void setSession(final DataProviderSessionIFace session) {

        for (Enumeration<Viewable> e = viewMapByName.elements(); e.hasMoreElements();) {
            e.nextElement().setSession(session);
        }

        for (MultiView mv : kids) {
            mv.setSession(session);
        }
    }

    /**
     * Increments to the next number in the series.
     */
    public void updateAutoNumbers() {
        FormViewObj formViewObj = getCurrentViewAsFormViewObj();
        if (formViewObj != null) {
            //if (formViewObj.getValidator() != null && formViewObj.getValidator().hasChanged())
            //{
            formViewObj.updateAutoNumbers();
            //}
        }

        for (MultiView mv : kids) {
            mv.updateAutoNumbers();
        }
    }

    /**
     * Sets all the resultSetControllers to the proper index.
     */
    public void setViewState(final Vector<ViewState> viewStateList, final AltViewIFace.CreationMode mode,
            final int vsInx) {
        if (viewStateList != null && vsInx < viewStateList.size()) {
            ViewState viewState = viewStateList.get(vsInx);

            if (vsInx > -1) {
                int inx = viewState.getInx();
                if (inx > -1) {
                    FormViewObj formViewObj = getCurrentViewAsFormViewObj();
                    if (formViewObj != null && formViewObj.getRsController() != null) {
                        formViewObj.getRsController().setIndex(inx);
                    }
                }
            }

            for (MultiView mv : kids) {
                if (mv.createWithMode == mode) {
                    mv.setViewState(viewStateList, mode, vsInx + 1);
                }
            }
        }
    }

    /**
     * Collects the current state of each view. This mostly captures the index of the RSC
     * @param viewStateList the list of view states
     * @param mode the mode
     * @param level the level
     */
    public void collectionViewState(final Vector<ViewState> viewStateList, final AltViewIFace.CreationMode mode,
            final int level) {
        AltViewIFace altView = currentViewable.getAltView();

        //String spaces = "                                                          ";
        //log.debug(spaces.substring(0, level)+"Current AltView: "+altView.getName()+"  Num: "+getViewables().size()+"  "+altView.getViewDef().getName());

        ViewState viewState = new ViewState(this, currentViewable, altView, altView.getViewDef());
        viewStateList.add(viewState);

        FormViewObj formViewObj = getCurrentViewAsFormViewObj();
        if (formViewObj != null && formViewObj.getRsController() != null) {
            int curInx = formViewObj.getRsController().getCurrentIndex();
            //log.debug(spaces.substring(0, level)+"  curInx: "+curInx);
            viewState.setInx(curInx);
        }

        if (currentViewable.getDataObj() instanceof FormDataObjIFace) {
            viewState.setIdentity(((FormDataObjIFace) currentViewable.getDataObj()).getIdentityTitle());
        }

        for (MultiView mv : kids) {
            if (mv.createWithMode == mode) {
                mv.collectionViewState(viewStateList, mode, level + 2);
            }
        }
    }

    /**
     * Call right before formShutdown is called, but the entire UI is still intact.
     */
    public void aboutToShutdown() {
        for (Enumeration<Viewable> e = viewMapByName.elements(); e.hasMoreElements();) {
            e.nextElement().aboutToShutdown();
        }
        for (MultiView mv : kids) {
            mv.aboutToShutdown();
        }
    }

    /**
     * Tells the MultiView the MV that it is being shutdown to be disposed.
     */
    public void shutdown() {
        mvParent = null;
        view = null;
        data = null;
        parentDataObj = null;
        currentViewable = null;

        for (Enumeration<Viewable> e = viewMapByName.elements(); e.hasMoreElements();) {
            e.nextElement().shutdown();
        }

        if (currentValidator != null) {
            currentValidator.cleanUp();
        }

        for (MultiView mv : kids) {
            mv.shutdown();
        }
        kids.clear();

        shutdownDisplayFrames();
    }

    /**
     * Tell the MultiView to shutdown and close all child ViewBasedDisplayIFace windows.
     */
    public void shutdownDisplayFrames() {
        if (displayFrames != null) {
            for (ViewBasedDisplayIFace vbd : displayFrames) {
                if (vbd != null) {
                    vbd.shutdown();
                    vbd.dispose();
                } else {
                    log.debug("Display frame was null!");
                }

            }
            displayFrames.clear();
        }
    }

    /**
     * Helper method to see if an option is turned on.
     * @param options the range of options that can be turned on
     * @param opt the actual option that may be turned on
     * @return true if the opt bit is on
     */
    public static boolean isOptionOn(final int options, final int opt) {
        return (options & opt) == opt;
    }

    /**
     * Debug Helper method
     * @param msg debug string
     * @param options the options to be printed
     */
    public static void printCreateOptions(final String msg, final int options) {
        System.err.println(" ");
        System.err.println(msg);
        System.err.println("RESULTSET_CONTROLLER  ["
                + ((options & MultiView.RESULTSET_CONTROLLER) == MultiView.RESULTSET_CONTROLLER ? "true" : "false")
                + "]");
        System.err.println("IS_NEW_OBJECT         ["
                + ((options & MultiView.IS_NEW_OBJECT) == MultiView.IS_NEW_OBJECT ? "true" : "false") + "]");
        System.err.println("VIEW_SWITCHER         ["
                + ((options & MultiView.VIEW_SWITCHER) == MultiView.VIEW_SWITCHER ? "true" : "false") + "]");
        System.err.println("HIDE_SAVE_BTN         ["
                + ((options & MultiView.HIDE_SAVE_BTN) == MultiView.HIDE_SAVE_BTN ? "true" : "false") + "]");
        System.err.println("IS_EDITTING           ["
                + ((options & MultiView.IS_EDITTING) == MultiView.IS_EDITTING ? "true" : "false") + "]");
        System.err.println("IS_SINGLE_OBJ         ["
                + ((options & MultiView.IS_SINGLE_OBJ) == MultiView.IS_SINGLE_OBJ ? "true" : "false") + "]");
        System.err.println("NO_SCROLLBARS         ["
                + ((options & MultiView.NO_SCROLLBARS) == MultiView.NO_SCROLLBARS ? "true" : "false") + "]");
        System.err.println("ADD_SEARCH_BTN        ["
                + ((options & MultiView.ADD_SEARCH_BTN) == MultiView.ADD_SEARCH_BTN ? "true" : "false") + "]");
        System.err.println("DONT_ADD_ALL_ALTVIEWS ["
                + ((options & MultiView.DONT_ADD_ALL_ALTVIEWS) == MultiView.DONT_ADD_ALL_ALTVIEWS ? "true"
                        : "false")
                + "]");
        System.err.println("USE_ONLY_CREATION_MODE["
                + ((options & MultiView.USE_ONLY_CREATION_MODE) == MultiView.USE_ONLY_CREATION_MODE ? "true"
                        : "false")
                + "]");
        System.err.println("DONT_USE_EMBEDDED_SEP ["
                + ((options & MultiView.DONT_USE_EMBEDDED_SEP) == MultiView.DONT_USE_EMBEDDED_SEP ? "true"
                        : "false")
                + "]");
        System.err.println("NO_MORE_BTN_FOR_SEP   ["
                + ((options & MultiView.NO_MORE_BTN_FOR_SEP) == MultiView.NO_MORE_BTN_FOR_SEP ? "true" : "false")
                + "]");
        System.err.println("COLLAPSE_SEPARATOR    ["
                + ((options & MultiView.COLLAPSE_SEPARATOR) == MultiView.COLLAPSE_SEPARATOR ? "true" : "false")
                + "]");
        System.err.println("INCLUDE_ADD_BTN       ["
                + ((options & MultiView.INCLUDE_ADD_BTN) == MultiView.INCLUDE_ADD_BTN ? "true" : "false") + "]");
        System.err.println(" ");
    }

    class ViewState {
        protected MultiView mv;
        protected Viewable viewable;
        protected AltViewIFace altView;
        protected ViewDefIFace viewDef;
        protected int inx;
        protected String identity = null;

        /**
         * @param mv
         * @param altView
         * @param viewDef
         * @param inx
         */
        public ViewState(MultiView mv, Viewable viewable, AltViewIFace altView, ViewDefIFace viewDef) {
            super();
            this.mv = mv;
            this.viewable = viewable;
            this.altView = altView;
            this.viewDef = viewDef;
            this.inx = -1;
            this.identity = null;
        }

        /**
         * @return the identity
         */
        public String getIdentity() {
            return identity;
        }

        /**
         * @param identity the identity to set
         */
        public void setIdentity(String identity) {
            this.identity = identity;
        }

        /**
         * @return the mv
         */
        public MultiView getMv() {
            return mv;
        }

        /**
         * @return the altView
         */
        public AltViewIFace getAltView() {
            return altView;
        }

        /**
         * @return the viewDef
         */
        public ViewDefIFace getViewDef() {
            return viewDef;
        }

        /**
         * @return the inx
         */
        public int getInx() {
            return inx;
        }

        /**
         * @param inx the inx to set
         */
        public void setInx(int inx) {
            this.inx = inx;
        }

        /**
         * @return the viewable
         */
        public Viewable getViewable() {
            return viewable;
        }

    }
}