All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.cuf.model.LOVMapper Maven / Gradle / Ivy

The newest version!
package net.sf.cuf.model;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.util.List;

/**
 * A LOVMapper is a value model that maps between a display list-of-values (LOV)
 * and their corresponding domain list-of-values.
 * TODO: support also a single List where display and domain values are attributes.
 */
public class LOVMapper extends AbstractValueModel
{
    /** the holder of the two LOV's, never null */
    private ValueModel[]>   mLOVsHolder;
    /** the value model we store/monitor fo the current domain value, never null */
    private ValueModel           mSelectedDomainValue;
    /** null or the selection in list we are watching */
    private SelectionInList      mSIL;
    /** marker if we are changing one model */
    private boolean                 mInChange;

    /** the index of the display list in the List[] */
    public static final int DOMAIN_INDEX = 0;
    /** the index of the display list in the List[] */
    public static final int DISPLAY_INDEX= 1;

    /**
     * Creates a new value model that maps between domain and display list-of-values.
     * @param pLOVsHolder the holder of the lists , must not be null
     * @param pSelectedDomainValue the value model that stores the selected domain value
     */
    public LOVMapper(final ValueModel[]> pLOVsHolder, final ValueModel pSelectedDomainValue)
    {
        if (pLOVsHolder==null)
        {
            throw new IllegalArgumentException("LOV's ValueModel must not be null");
        }
        List[] value= pLOVsHolder.getValue();
        if ((value!=null) && (value.length!=2))
        {
            throw new IllegalArgumentException("LOV's value must either be null or a List[2]");
        }
        if (pSelectedDomainValue==null)
        {
            throw new IllegalArgumentException("selected domain ValueModel must not be null");
        }
        mLOVsHolder         = pLOVsHolder;
        mSelectedDomainValue= pSelectedDomainValue;
        mSIL                = null;

        mLOVsHolder         .onChangeSend(this, "lofsChanged");
        mSelectedDomainValue.onChangeSend(this, "domainValueChanged");
    }

    /**
     * Returns the current display list.
     * @return null or the display list object
     */
    public Object getValue()
    {
        Object value= mLOVsHolder.getValue();
        if (value==null)
        {
            return null;
        }
        else
        {
            List[] lofs= (List[])value;
            return lofs[DISPLAY_INDEX];
        }
    }

    /**
     * Throws a UnsupportedOperationException.
     * @param pValue       not used
     * @param pIsSetForced not used
     * @throws UnsupportedOperationException always thrown
     */
    public void setValue(final Object pValue, final boolean pIsSetForced)
    {
        throw new UnsupportedOperationException("a LOVMapper is read-only");
    }

    /**
     * Returns always false.
     * @return false
     */
    public boolean isEditable()
    {
        return false;
    }


    /*
     * override the listener add/remove methods to detect a SelectinInList
     */

    public void onChangeSend(final Object pDependent, final String pMethodName)
    {
        super.onChangeSend(pDependent, pMethodName);
        checkAddDependent(pDependent);
    }

    public void addChangeListener(final ChangeListener pDependent)
    {
        super.addChangeListener(pDependent);
        checkAddDependent(pDependent);
    }

    /**
     * Common add check code.
     * @param pDependent the listener to add
     */
    private void checkAddDependent(final Object pDependent)
    {
        if (pDependent instanceof SelectionInList)
        {
            if (mSIL!=null)
            {
                mSIL.retractInterestsFor(this);
            }
            mSIL= (SelectionInList)pDependent;
            mSIL.selectionHolder().onChangeSend(this, "selectionChanged");
        }
    }

    public void retractInterestsFor(final Object pDependent)
    {
        super.retractInterestsFor(pDependent);
        checkRemoveDependent(pDependent);
    }


    public void removeChangeListener(final ChangeListener pDependent)
    {
        super.removeChangeListener(pDependent);
        checkRemoveDependent(pDependent);
    }

    /**
     * Common remove listener code.
     * @param pDependent the listener
     */
    private void checkRemoveDependent(final Object pDependent)
    {
        //noinspection ObjectEquality
        if (mSIL==pDependent)
        {
            if (mSIL!=null)
            {
                mSIL.retractInterestsFor(this);
            }
            mSIL= null;
        }
    }

    /*
     * callback methods of the various ValueModel's
     */

    /**
     * Callback that both list changed
     * @param pEvent not used
     */
    @SuppressWarnings({"UnusedDeclaration"})
    public void lofsChanged(final ChangeEvent pEvent)
    {
        List[] value= mLOVsHolder.getValue();
        if ((value!=null) && (value.length!=2))
        {
            throw new IllegalArgumentException("LOV's value must either be null or a List[2]");
        }

        // this will update a SelectionInList that monitors us
        fireStateChanged();
    }

    /**
     * This is a callback from the domain value and will update the SelectionInList index.
     * @param pEvent not used
     */
    @SuppressWarnings({"UnusedDeclaration"})
    public void domainValueChanged(final ChangeEvent pEvent)
    {
        // ignore callbacks triggered by ourselfs
        if (mInChange)
        {
            return;
        }

        Object domainValue= mSelectedDomainValue.getValue();
        int    index      = SelectionInList.NO_SELECTION;
        if (domainValue != null)
        {
            List[] lovs= mLOVsHolder.getValue();
            if (lovs!=null)
            {
                List keys= lovs[DOMAIN_INDEX];
                index= keys.indexOf(domainValue);
            }
        }

        if (mSIL!=null)
        {
            try
            {
                mInChange= true;
                mSIL.selectionHolder().setValue(index);
            }
            finally
            {
                mInChange= false;
            }
        }
    }

    /**
     * This is a callback from the SelectionInList and will update the domain value.
     * @param pEvent not used
     */
    @SuppressWarnings({"UnusedDeclaration"})
    public void selectionChanged(final ChangeEvent pEvent)
    {
        // ignore callbacks triggered by ourselfs
        if (mInChange)
        {
            return;
        }

        int index= mSIL.getIndex();
        if (index<0)
        {
            mSelectedDomainValue.setValue(null);
        }
        else
        {
            List[] lovs= mLOVsHolder.getValue();
            if (lovs!=null)
            {
                List keys= lovs[DOMAIN_INDEX];
                try
                {
                    mInChange= true;
                    mSelectedDomainValue.setObjectValue(keys.get(index));
                }
                finally
                {
                    mInChange= false;
                }
            }
        }
    }
}