Package org.gocha.collection.list

Source Code of org.gocha.collection.list.BasicEventListCancel

/*******************************************************************************
gocha.org-lib-java Библеотека общего назначения
(с) Камнев Георгий Павлович 2009 GPLv2

Данная программа является свободным программным обеспечением. Вы вправе
распространять ее и/или модифицировать в соответствии с условиями версии 2
либо по вашему выбору с условиями более поздней версии
Стандартной Общественной Лицензии GNU, опубликованной Free Software Foundation.

Мы распространяем данную программу в надежде на то, что она будет вам полезной,
однако НЕ ПРЕДОСТАВЛЯЕМ НА НЕЕ НИКАКИХ ГАРАНТИЙ,
в том числе ГАРАНТИИ ТОВАРНОГО СОСТОЯНИЯ ПРИ ПРОДАЖЕ
и ПРИГОДНОСТИ ДЛЯ ИСПОЛЬЗОВАНИЯ В КОНКРЕТНЫХ ЦЕЛЯХ.
Для получения более подробной информации ознакомьтесь
со Стандартной Общественной Лицензией GNU.

Вместе с данной программой вы должны были получить экземпляр
Стандартной Общественной Лицензии GNU.
Если вы его не получили, сообщите об этом в Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*******************************************************************************/

package org.gocha.collection.list;

import org.gocha.collection.ObjectChangeCancel;
import org.gocha.collection.ObjectChangeCancelEvent;
import org.gocha.collection.ObjectChanged;
import org.gocha.collection.ObjectChangeCancelListener;
import org.gocha.collection.ObjectChangedListener;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
* Список поддерживающий контроль измения своего состава элементов.
* Может уведолять слушателей о операциях над элементами списка (встака, удаление элементов, ....).
* Может отменять операции над элементами списка (встака, удаление элементов, ....).
*
* Список не реализует хранеие данных, для этого он использует другой список (List).
* Все операции манипуляции с элементами, он делегирует списку
*
* @author gocha
* @param <E> Тип элементов списка
*/
public class BasicEventListCancel<E> extends ListWrapper<E> implements EventListCancel<E>
{
    /**
     * Конструктор
     * @param list Список хранящий элементы
     */
    public BasicEventListCancel(List<E> list)
    {
        super(list);

        for (E it : list)
        {
            added(it);
        }
    }

    /**
     * Указывает модель отмены операций (CANCELMODEL_FOR_ALL,CANCELMODEL_FOR_EACH)
     */
    public int cancelModel = CANCELMODEL_FOR_EACH;

    /**
     * Модель отмены для всех -
     * Если в процессе операции происходит "отмена" для элемента, то операция отменяется для всех последующих элементов
     */
    public static final int CANCELMODEL_FOR_ALL = 1;

    /**
     * Модель отмены для каждого -
     * Если в процессе операции происходит "отмена" для элемента, то операция отменяется только для указанного
     */
    public static final int CANCELMODEL_FOR_EACH = 2;

    // /////////////////////////////////////////////////////////////////////////
    /**
     * Вызывается когда добавляется элемент в коллекцию (операции add, insert, ...).
     * Если элемент реализует интерфейс ObjectChanged, то устанавливается слушатель, с последующей генерацией сообщений Update.
     * Вызывает onInserted(), onSelfChanged()
     * @param e Элемент.
     */
    protected void added(E e)
    {
        int index = indexOf(e);

        fireEventListArgs(
            new BasicEventListArgs<E>(
                this,EventListAction.Insert,e,index));

        if (e == null)
        {
            return;
        }
        if (e instanceof ObjectChanged)
        {
            ObjectChanged iOC = (ObjectChanged) e;
            iOC.addObjectChangedListener(getItemChangedListener());
        }
        if (e instanceof ObjectChangeCancel)
        {
          ObjectChangeCancel iOC = (ObjectChangeCancel) e;
            iOC.addObjectChangeCancelListener(getItemChangeCancelListener());
        }
    }

    /**
     * Вызывается когда удаляется элемент из коллекции (операции remove, clear, ...).
     * Если элемент реализует интерфейс ObjectChanged, то удаляется слушатель.
     * Вызывает onDeleted(), onSelfChanged()
     * @param e Элемент.
     */
    protected void removed(E e, int index)
    {
        fireEventListArgs(
            new BasicEventListArgs<E>(
                this,EventListAction.Delete,e,index));

        if (e == null)
        {
            return;
        }
        if (e instanceof ObjectChanged)
        {
            ObjectChanged iOC = (ObjectChanged) e;
            iOC.removeObjectChangedListener(getItemChangedListener());
        }
        if (e instanceof ObjectChangeCancel)
        {
          ObjectChangeCancel iOC = (ObjectChangeCancel) e;
            iOC.removeObjectChangeCancelListener(getItemChangeCancelListener());
        }
    }

    //************************************************************************
    private ObjectChangedListener itemChangedListener = null;

    /**
     * Возвращает слушателя элементов списка
     * @return Слушатель
     */
    public ObjectChangedListener getItemChangedListener()
    {
        if (itemChangedListener == null)
        {
            itemChangedListener = new ObjectChangedListener()
            {
              @Override
                public void changed(Object sender)
                {
                    onItemChanged(sender);
                }
            };
        }
        return itemChangedListener;
    }

    /**
     * Вызывает образотчиков сообщения Update для указанного элемента
     * @param item Элемент
     */
    @SuppressWarnings("unchecked")
  protected void onItemChanged(Object item)
    {
        try
        {
            E eItem = (E) item;
            int index = indexOf(eItem);
           
            fireEventListArgs(
                new BasicEventListArgs<E>(
                    this,EventListAction.Update,eItem,index));
        }
        catch (ClassCastException ex)
        {
        }
    }

    //************************************************************************
    private ObjectChangeCancelListener itemChangeCancelListener = null;
   
    /**
     * Возвращает слушателя элементов списка
     * @return Слушатель
     */
    public ObjectChangeCancelListener getItemChangeCancelListener()
    {
        if (itemChangeCancelListener == null)
        {
          itemChangeCancelListener = new ObjectChangeCancelListener()
            {
              @Override
                public void changing(ObjectChangeCancelEvent evnt)
                {
                onItemChanging(evnt);
                }
            };
        }
        return itemChangeCancelListener;
    }

    /**
     * Вызывает образотчиков сообщения Update для указанного элемента
     * @param evnt Элемент
     */
  @SuppressWarnings("unchecked")
  protected void onItemChanging(ObjectChangeCancelEvent evnt)
    {
        try
        {
            E eItem = (E) evnt.getObject();
            int index = indexOf(eItem);
           
            BasicEventListCancelChangeArgs<E> evnt2 =
              (BasicEventListCancelChangeArgs<E>)
                fireEventListCancelArgs(
                    new BasicEventListCancelChangeArgs<E>(
                        this,EventListAction.Update,eItem,false, evnt, index));
           
            if( evnt2.getCancel() )
            {
              evnt.setCancel(true);
              evnt.setException(null);
             
              if( evnt2.getException()!=null )
              {
                throw evnt.getException();
              }
            }
        }
        catch (ClassCastException ex)
        {
        }
    }

    // /////////////////////////////////////////////////////////////////////////
    /**
     * Добавление объекта в список
     * @param e Объект
     * @return Факт добавления
     */
    @Override
    public boolean add(E e)
    {
        int index = size();

      EventListCancelArgs<E> evnt =
            fireEventListCancelArgs(
                new BasicEventListCancelArgs<E>(
                    this,EventListAction.Insert,e,false,index));

     
        if (evnt.getCancel()) // DENY
        {
            if (evnt.getException() != null)
            {
                throw evnt.getException();
            }
            else
            {
                return false;
            }
        }
        boolean res = super.add(e);
        if (res)
        {
            added(e);
        }
        return res;
    }

    /**
     * Добавление объекта в список, в заданную позицию
     * @param index Позиция
     * @param element Объект
     */
    @Override
    public void add(int index, E element)
    {
      EventListCancelArgs<E> evnt =
            fireEventListCancelArgs(
                new BasicEventListCancelArgs<E>(
                    this,EventListAction.Insert,element,false,index));

        if (evnt.getCancel()) // DENY
        {
            if (evnt.getException() != null)
            {
                throw evnt.getException();
            }
            else
            {
                return;
            }
        }
        super.add(index, element);
        added(element);
    }

    /**
     * Добавление объектов в список
     * @param c Объекты
     * @return Факт добавления
     */
    @Override
    public boolean addAll(Collection<? extends E> c)
    {
        if (this.cancelModel == CANCELMODEL_FOR_ALL)
        {
            int index = size()-1;
            for (E e : c)
            {
                index++;

              EventListCancelArgs<E> evnt =
                    fireEventListCancelArgs(
                        new BasicEventListCancelArgs<E>(
                            this,EventListAction.Insert,e,false,index));

                if (evnt.getCancel()) // DENY
                {
                    if (evnt.getException() != null)
                    {
                        throw evnt.getException();
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            boolean res = super.addAll(c);

            if (res)
            {
                for (E e : c)
                {
                    added(e);
                }
            }

            return res;
        }
        else if (this.cancelModel == CANCELMODEL_FOR_EACH)
        {
            int index = size()-1;
            for (E e : c)
            {
                index++;

              EventListCancelArgs<E> evnt =
                    fireEventListCancelArgs(
                        new BasicEventListCancelArgs<E>(
                            this,EventListAction.Insert,e,false,index));

                if (evnt.getCancel()) // DENY
                {
                    if (evnt.getException() != null)
                    {
                        throw evnt.getException();
                    }
                    else
                    {
                        index--;
                        continue;
                    }
                }
               
                super.add(e);
                added(e);
            }

            return true;
        }

        return false;
    }

    /**
     * Добавление объектов в список
     * @param index Позиция
     * @param c Объекты
     * @return Факт добавления
     */
    @Override
    public boolean addAll(int index, Collection<? extends E> c)
    {
        if (this.cancelModel == CANCELMODEL_FOR_ALL)
        {
            int cc = 0;
            for (E e : c)
            {
                int eindex = index + cc;
                cc++;

              EventListCancelArgs<E> evnt =
                    fireEventListCancelArgs(
                        new BasicEventListCancelArgs<E>(
                            this,EventListAction.Insert,e,false,eindex));

                if (evnt.getCancel()) // DENY
                {
                    if (evnt.getException() != null)
                    {
                        throw evnt.getException();
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            boolean res = super.addAll(index, c);

            if (res)
            {
                for (E e : c)
                {
                    added(e);
                }
            }

            return res;
        }
        else if (this.cancelModel == CANCELMODEL_FOR_EACH)
        {
            int eindex = index - 1;
            for (E e : c)
            {
                eindex++;

              EventListCancelArgs<E> evnt =
                    fireEventListCancelArgs(
                        new BasicEventListCancelArgs<E>(
                            this,EventListAction.Insert,e,false,eindex));

              if (evnt.getCancel()) // DENY
                {
                    if (evnt.getException() != null)
                    {
                        throw evnt.getException();
                    }
                    else
                    {
                        eindex--;
                        continue;
                    }
                }
               
                super.add(index, e);
                added(e);
                index++;
            }

            return true;
        }

        return false;
    }

    // ////////////////////////////////////////////////////////////////////////////
    /**
     * Удаление объектов из списка
     */
    @Override
    @SuppressWarnings("unchecked")
    public void clear()
    {
        Map<Object,Integer> indexes = new HashMap<Object, Integer>();
        for( Object o : this )
        {
            indexes.put(o, indexOf(o));
        }

        if (this.cancelModel == CANCELMODEL_FOR_ALL)
        {
            Object[] items = super.toArray();
            for (Object o : items)
            {
                try
                {
                    E e = (E) o;
                    int index = indexOf(o);

                  EventListCancelArgs<E> evnt =
                        fireEventListCancelArgs(
                            new BasicEventListCancelArgs<E>(
                                this,EventListAction.Delete,e,false,index));

                    if (evnt.getCancel()) // DENY
                    {
                        if (evnt.getException() != null)
                        {
                            throw evnt.getException();
                        }
                        else
                        {
                            return;
                        }
                    }
                }
                catch (ClassCastException ex)
                {
                    continue;
                }
            }

            super.clear();

            for (Object o : items)
            {
                try
                {
                    E e = (E) o;
                    removed(e,indexes.get(o));
                }
                catch (ClassCastException ex)
                {
                }
            }
        }
        else if (this.cancelModel == CANCELMODEL_FOR_EACH)
        {
            Object[] items = super.toArray();
            for (Object o : items)
            {
                try
                {
                    E e = (E) o;
                    int index = indexOf(o);

                  EventListCancelArgs<E> evnt =
                        fireEventListCancelArgs(
                            new BasicEventListCancelArgs<E>(
                                this,EventListAction.Delete,e,false,index));

                    if (evnt.getCancel()) // DENY
                    {
                        if (evnt.getException() != null)
                        {
                            throw evnt.getException();
                        }
                        else
                        {
                            continue;
                        }
                    }
                    super.remove(e);
                    removed(e,indexes.get(o));
                }
                catch (ClassCastException ex)
                {
                    continue;
                }
            }
        }
    }

    /**
     * Удаление объекта из списка
     * @param o Объект
     * @return Факт удаления
     */
    @Override
    @SuppressWarnings("unchecked")
    public boolean remove(Object o)
    {
        Map<Object,Integer> indexes = new HashMap<Object, Integer>();
        for( Object ok : this )
        {
            indexes.put(ok, indexOf(ok));
        }
       
        try
        {
            E e = (E) o;
            int index = indexOf(o);

          EventListCancelArgs<E> evnt =
                fireEventListCancelArgs(
                    new BasicEventListCancelArgs<E>(
                        this,EventListAction.Delete,e,false,index));

            if (evnt.getCancel()) // DENY
            {
                if (evnt.getException() != null)
                {
                    throw evnt.getException();
                }
                else
                {
                    return false;
                }
            }
        }
        catch (ClassCastException ex)
        {
        }

        boolean res = super.remove(o);

        if (res)
        {
            try
            {
                E e = (E) o;
                removed(e,indexes.get(o));
            }
            catch (ClassCastException ex)
            {
            }
        }

        return res;
    }

    /**
     * Удаление объекта из списка
     * @param index Индекс элемента
     * @return Удаленный элемент
     */
    @Override
    public E remove(int index)
    {
        E e = super.get(index);
//        int index = indexOf(e)
     
        EventListCancelArgs<E> evnt =
            fireEventListCancelArgs(
                new BasicEventListCancelArgs<E>(
                    this,EventListAction.Delete,e,false,index));

        if (evnt.getCancel()) // DENY
        {
            if (evnt.getException() != null)
            {
                throw evnt.getException();
            }
            else
            {
                return null;
            }
        }
        E ee = super.remove(index);
        removed(ee,index);
        return ee;
    }

    /**
     * Удаляет группу объектов из списка
     * @param c Группа объектов
     * @return Факт удаления
     */
    @Override
    @SuppressWarnings("unchecked")
    public boolean removeAll(Collection<?> c)
    {
        Map<Object,Integer> indexes = new HashMap<Object, Integer>();
        for( Object o : this )
        {
            indexes.put(o, indexOf(o));
        }
       
        if (this.cancelModel == CANCELMODEL_FOR_ALL)
        {
            for (Object o : c)
            {
                try
                {
                    E e = (E) o;
                    int index = indexOf(o);

                    EventListCancelArgs<E> evnt =
                        fireEventListCancelArgs(
                            new BasicEventListCancelArgs<E>(
                                this,EventListAction.Delete,e,false,index));

                    if (evnt.getCancel()) // DENY
                    {
                        if (evnt.getException() != null)
                        {
                            throw evnt.getException();
                        }
                        else
                        {
                            return false;
                        }
                    }
                }
                catch (ClassCastException ex)
                {
                }
            }

            boolean res = super.removeAll(c);

            if (res)
            {
                for (Object o : c)
                {
                    try
                    {
                        E e = (E) o;
                        removed(e,indexes.get(o));
                    }
                    catch (ClassCastException ex)
                    {
                    }
                }
            }

            return res;
        }
        else if (this.cancelModel == CANCELMODEL_FOR_EACH)
        {
            for (Object o : c)
            {
                try
                {
                    E e = (E) o;
                    int index = indexOf(o);

                    EventListCancelArgs<E> evnt =
                        fireEventListCancelArgs(
                            new BasicEventListCancelArgs<E>(
                                this,EventListAction.Delete,e,false,index));

                    if (evnt.getCancel()) // DENY
                    {
                        if (evnt.getException() != null)
                        {
                            throw evnt.getException();
                        }
                        else
                        {
                            return false;
                        }
                    }

                    super.remove(e);
                    removed(e,indexes.get(o));
                }
                catch (ClassCastException ex)
                {
                }
            }
        }

        return false;
    }

    /**
     * Удаляет объекты из списка, не входящиие в указанную группу объектов
     * @param c Группа объектов
     * @return Факт удаления
     */
    @Override
    @SuppressWarnings("unchecked")
    public boolean retainAll(Collection<?> c)
    {
        Map<Object,Integer> indexes = new HashMap<Object, Integer>();
        for( Object o : this )
        {
            indexes.put(o, indexOf(o));
        }
       
        if (this.cancelModel == CANCELMODEL_FOR_ALL)
        {
            for (Object o : this)
            {
                if (!c.contains(o))
                {
                    E e = (E) o;
                    int index = indexOf(o);

                    EventListCancelArgs<E> evnt =
                        fireEventListCancelArgs(
                            new BasicEventListCancelArgs<E>(
                                this,EventListAction.Delete,e,false,index));

                    if (evnt.getCancel()) // DENY
                    {
                        if (evnt.getException() != null)
                        {
                            throw evnt.getException();
                        }
                        else
                        {
                            return false;
                        }
                    }
                }
            }

            Object[] beforeItems = super.toArray();
            boolean res = super.retainAll(c);
            Object[] afterItems = super.toArray();

            if (res)
            {
                LinkedList<Object> dels = new LinkedList<Object>();

                for (Object bi : beforeItems)
                {
                    if (bi == null)
                    {
                        continue;
                    }
                    boolean found = false;
                    for (Object ai : afterItems)
                    {
                        if (bi == ai)
                        {
                            found = true;
                        }
                    }

                    if (!found)
                    {
                        dels.add(bi);
                    }
                }

                for (Object delObj : dels)
                {
                    try
                    {
                        removed((E) delObj,indexes.get(delObj));
                    }
                    catch (ClassCastException ex)
                    {
                    }
                }
            }

            return res;
        }
        else if (this.cancelModel == CANCELMODEL_FOR_EACH)
        {
            Object[] items = super.toArray();
            for (Object o : items)
            {
                try
                {
                    if (!c.contains(o))
                    {
                        E e = (E) o;
                        int index = indexOf(o);

                        EventListCancelArgs<E> evnt =
                            fireEventListCancelArgs(
                                new BasicEventListCancelArgs<E>(
                                    this,EventListAction.Delete,e,false,index));

                        if (evnt.getCancel()) // DENY
                        {
                            if (evnt.getException() != null)
                            {
                                throw evnt.getException();
                            }
                            else
                            {
                                return false;
                            }
                        }

                        super.remove(e);
                        removed(e,indexes.get(e));
                    }
                }
                catch (ClassCastException ex)
                {
                }
            }
        }

        return false;
    }

    // /////////////////////////////////////////////////////////////////////////
    /**
     * Заменяет объект в указанной позиции
     * @param index Позиция элемента
     * @param element Новый элемент
     * @return Старый элемент
     */
    @Override
    public E set(int index, E element)
    {
        E forDeleting = super.get(index);

        EventListCancelArgs<E> evnt =
            fireEventListCancelArgs(
                new BasicEventListCancelArgs<E>(
                    this,EventListAction.Delete,forDeleting,false,index));

        if (evnt.getCancel()) // DENY
        {
            if (evnt.getException() != null)
            {
                throw evnt.getException();
            }
            else
            {
                return element;
            }
        }

        EventListCancelArgs<E> evnt2 =
            fireEventListCancelArgs(
                new BasicEventListCancelArgs<E>(
                    this,EventListAction.Insert,element,false,index));

        if (evnt2.getCancel()) // DENY
        {
            if (evnt2.getException() != null)
            {
                throw evnt2.getException();
            }
            else
            {
                return forDeleting;
            }
        }
       
        E res = super.set(index, element);

        removed(res,index);
        added(element);

        return res;
    }

    // /////////////////////////////////////////////////////////////////////////
    // Событие changed
    // /////////////////////////////////////////////////////////////////////////
    private Vector<ObjectChangedListener> changed = new Vector<ObjectChangedListener>();

    /**
     * Добавляет слушателя на реакцию изменения списка.<br>
     * @param listener
     *            слушатель
     */
    public void addObjectChangedListener(ObjectChangedListener listener)
    {
        if (listener == null)
        {
            return;
        }
        changed.add(listener);
    }

    /**
     * Удаляет слушателья с реакции изменения списка.
     *
     * @param listener
     *            слушатель
     */
    public void removeObjectChangedListener(ObjectChangedListener listener)
    {
        changed.remove(listener);
    }
   
    /**
     * Вывзваеться для отправки сообщения слушателям о измении списка
     */
    protected void onSelfChanged()
    {
        for (ObjectChangedListener listener : changed)
        {
            if (listener == null)
            {
                continue;
            }
            listener.changed(this);
        }
    }

    private Vector<EventListListener<E>> listEventListeners = new Vector<EventListListener<E>>();
   
    /* (non-javadoc)
     * @see org.gocha.collection.list.IEventListSender#addEventListListener
     */
    @Override
  public void addEventListListener(EventListListener<E> listener)
  {
        if (listener == null)
        {
            return;
        }
        listEventListeners.add(listener);
  }

    /* (non-javadoc)
     * @see org.gocha.collection.list.IEventListSender#removeEventListListener
     */
  @Override
  public void removeEventListListener(EventListListener<E> listener)
  {
    listEventListeners.remove(listener);
  }
 
  /**
   * Вызываеться для отправки сообщения измения элементов списка
   * @param evnt Сообщение
   */
  protected void fireEventListArgs(EventListArgs<E> evnt)
  {
    for (EventListListener<E> listener : listEventListeners)
        {
            if (listener == null)
            {
                continue;
            }
            listener.listItemsChanged(evnt);
        }
  }

    private Vector<EventListCancelListener<E>> listEventCancelListeners
      = new Vector<EventListCancelListener<E>>();
   
    /* (non-javadoc)
     * @see org.gocha.collection.list.IEventCancelListSender#addEventListCancelListener
     */
    @Override
  public void addEventListCancelListener(EventListCancelListener<E> listener)
  {
        if (listener == null)
        {
            return;
        }
        listEventCancelListeners.add(listener);
  }

    /* (non-javadoc)
     * @see org.gocha.collection.list.IEventCancelListSender#removeEventListCancelListener
     */
  @Override
  public void removeEventListCancelListener(EventListCancelListener<E> listener)
  {
    listEventCancelListeners.remove(listener);
  }
 
  /**
   * Вызываеться для отправки сообщения измения элементов списка
   * @param evnt Сообщение
   * @return Сообщение
   */
  protected EventListCancelArgs<E> fireEventListCancelArgs(EventListCancelArgs<E> evnt)
  {
    for (EventListCancelListener<E> listener : listEventCancelListeners)
        {
            if (listener == null)
            {
                continue;
            }
            listener.listItemsChanging(evnt);
        }
    return evnt;
  }
}
TOP

Related Classes of org.gocha.collection.list.BasicEventListCancel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.