Package org.gocha.collection.list

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

/*******************************************************************************
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 java.util.ArrayList;
import org.gocha.collection.ObjectChanged;
import org.gocha.collection.ObjectChangedListener;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
* Класс создающий уведомления об изменении списка.
* @author Камнев Георгий Павлович
*/
public class BasicEventList<E> extends ListWrapper<E> implements ObjectChanged, EventList<E>
{
    public BasicEventList()
    {
        this(new ArrayList<E>());
    }

  /**
     * Конструктор.
     *
     * @param list
     *            Обвараичваемый список
     * @throws NullPointerException
     *             если list==null
     */
    public BasicEventList(List<E> list) throws NullPointerException
    {
        super(list);
       
        if (list == null)
        {
            throw new NullPointerException();
        }
        for (E it : list)
        {
            attach(it);
        }
       
        addEventListListener(new EventListAdapter<E>()
        {
      @Override
            public void inserted(EventListArgs<E> evnt)
            {
                if (evnt == null || evnt.getItem() == null)
                    return;
               
                attach(evnt.getItem());
            }

      @Override
      protected void deleted(EventListArgs<E> evnt)
      {
                if (evnt == null || evnt.getItem() == null)
                    return;

                detach(evnt.getItem());
      }
        });
    }
   
    private Vector<ObjectChangedListener> changed = new Vector<ObjectChangedListener>();

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

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

    private ObjectChangedListener getItemListener()
    {
        if (itemListener == null)
        {
            itemListener = new ObjectChangedListener()
            {
                @Override
                public void changed(Object sender)
                {
                    onItemChanged(sender);
                }
            };
        }
        return itemListener;
    }
   
    /**
     * Вызывается при добавлении объекта. Доавляет своего слушателя изменения
     * (ObjectChangedListener) объекта item
     *
     * @param item
     *            Объект коллекции
     */
    protected void attach(E item)
    {
        //onSelfChanged();

        if (item == null)
        {
            return;
        }
        if (item instanceof ObjectChanged)
        {
            ObjectChanged iOC = (ObjectChanged) item;
            iOC.addObjectChangedListener(getItemListener());
        }
    }

    /**
     * Вызывается при удаления объекта. Удаляет своего слушателя изменения
     * (ObjectChangedListener) объекта item
     *
     * @param item
     *            Объект коллекции
     */
    protected void detach(E item)
    {
        try
        {
            //onSelfChanged();
        }
        finally
        {
            if (item == null)
            {
                return;
            }
            if (item instanceof ObjectChanged)
            {
                ObjectChanged iOC = (ObjectChanged) item;
                iOC.removeObjectChangedListener(getItemListener());
            }
        }
    }
   
    /**
     * Вызываается при изменении объекта коллекции. Вызывает реакции update для
     * коллекции и свою реакцию изменения ObjectChanged
     *
     * @param item
     *            Объект который изменился в коллекции
     */
    @SuppressWarnings("unchecked")
    protected void onItemChanged(Object item)
    {
        try
        {
            E eItem = (E) item;
           
            fireEventListArgs(
                new BasicEventListArgs<E>(
                    this,EventListAction.Update,eItem,indexOf(item)));
        }
        catch (ClassCastException ex)
        {
        }
    }

    private Collection<EventListListener<E>> listEventListeners = new HashSet<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);
        }
  }

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

        if (res)
        {
            int index = indexOf(e);

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

    /**
     * Добавление объекта в список, в заданную позицию
     * @param index Позиция
     * @param element Объект
     */
    @Override
    public void add(int index, E element)
    {
        super.add(index, element);

        fireEventListArgs(
            new BasicEventListArgs<E>(
                this,EventListAction.Insert,element,indexOf(element)));
    }

    /**
     * Добавление объектов в список
     * @param c Объекты
     * @return Факт добавления
     */
    @Override
    public boolean addAll(Collection<? extends E> c)
    {
        boolean res = super.addAll(c);

        if (res)
        {
            for (E e : c)
            {
                fireEventListArgs(
                    new BasicEventListArgs<E>(
                        this,EventListAction.Insert,e,indexOf(e)));
            }
        }

        return res;
    }

    /**
     * Добавление объектов в список, в заданную позицию
     * @param index Позиция
     * @param c Объекты
     * @return Факт добавления
     */
    @Override
    public boolean addAll(int index, Collection<? extends E> c)
    {
        boolean res = super.addAll(index, c);

        if (res)
        {
            for (E e : c)
            {
                fireEventListArgs(
                    new BasicEventListArgs<E>(
                        this,EventListAction.Insert,e,indexOf(e)));
            }
        }

        return res;
    }

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

        Object[] items = super.toArray();
        super.clear();

        for (Object o : items)
        {
            try
            {
                E e = (E) o;

                fireEventListArgs(
                    new BasicEventListArgs<E>(
                        this,EventListAction.Delete,e,indexes.get(o)));
            }
            catch (ClassCastException ex)
            {
                continue;
            }
        }
    }

    /**
     * Удаление объекта из списка
     * @param o Объект
     * @return Факт удаления
     */
    @SuppressWarnings("unchecked")
    @Override
    public boolean remove(Object o)
    {
        int index = indexOf(o);

        @SuppressWarnings("element-type-mismatch")
        boolean res = super.remove(o);

        if (res)
        {
            try
            {
                fireEventListArgs(
                    new BasicEventListArgs<E>(
                        this,EventListAction.Delete,(E)o,index));
            }
            catch (ClassCastException ex)
            {
            }
        }

        return res;
    }

    /**
     * Удаление объекта из списка
     * @param index Индекс элемента
     * @return Удаленный элемент
     */
    @Override
    public E remove(int index)
    {
        E item = super.remove(index);

        fireEventListArgs(
            new BasicEventListArgs<E>(
                this,EventListAction.Delete,item,index));

        return item;
    }

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

        boolean res = super.removeAll(c);

        if (res)
        {
            for (Object o : c)
            {
                try
                {
                    fireEventListArgs(
                        new BasicEventListArgs<E>(
                            this,EventListAction.Delete,(E)o,indexes.get(o)));
                }
                catch (ClassCastException ex)
                {
                }
            }
        }

        return res;
    }

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

        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
                {
                    fireEventListArgs(
                        new BasicEventListArgs<E>(
                            this,EventListAction.Delete,(E) delObj,indexes.get(delObj)));
                }
                catch (ClassCastException ex)
                {
                }
            }
        }

        return res;
    }

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

        fireEventListArgs(
            new BasicEventListArgs<E>(
                this,EventListAction.Delete,(E) deleted,index));

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

        return deleted;
    }
}
TOP

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

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.