io.ebean.common.BeanList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ebean Show documentation
Show all versions of ebean Show documentation
composite of common runtime dependencies for all platforms
package io.ebean.common;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanCollectionAdd;
import io.ebean.bean.BeanCollectionLoader;
import io.ebean.bean.EntityBean;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* List capable of lazy loading.
*/
public final class BeanList extends AbstractBeanCollection implements List, BeanCollectionAdd {
private static final long serialVersionUID = 1L;
/**
* The underlying List implementation.
*/
private List list;
/**
* Specify the underlying List implementation.
*/
public BeanList(List list) {
super();
this.list = list;
}
/**
* Uses an ArrayList as the underlying List implementation.
*/
public BeanList() {
this(new ArrayList<>());
}
/**
* Used to create deferred fetch proxy.
*/
public BeanList(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
super(loader, ownerBean, propertyName);
}
@Override
public void reset(EntityBean ownerBean, String propertyName) {
this.ownerBean = ownerBean;
this.propertyName = propertyName;
this.list = null;
}
@Override
public boolean isSkipSave() {
return list == null || (list.isEmpty() && !holdsModifications());
}
@Override
@SuppressWarnings("unchecked")
public void addEntityBean(EntityBean bean) {
list.add((E) bean);
}
@Override
@SuppressWarnings("unchecked")
public void loadFrom(BeanCollection> other) {
if (list == null) {
list = new ArrayList<>();
}
list.addAll((Collection extends E>) other.getActualDetails());
}
@Override
@SuppressWarnings("unchecked")
public void internalAdd(Object bean) {
if (list == null) {
list = new ArrayList<>();
}
if (bean != null) {
list.add((E) bean);
}
}
@Override
public void internalAddWithCheck(Object bean) {
if (list == null || !containsInstance(bean)) {
internalAdd(bean);
}
}
/**
* Contains using instance equality for List (specifically not .equals() based).
*/
private boolean containsInstance(Object bean) {
for (Object element : list) {
if (element == bean) {
return true;
}
}
return false;
}
@Override
public boolean checkEmptyLazyLoad() {
if (list == null) {
list = new ArrayList<>();
return true;
} else {
return false;
}
}
private void initClear() {
synchronized (this) {
if (list == null) {
if (!disableLazyLoad && modifyListening) {
lazyLoadCollection(true);
} else {
list = new ArrayList<>();
}
}
}
}
private void init() {
synchronized (this) {
if (list == null) {
if (disableLazyLoad) {
list = new ArrayList<>();
} else {
lazyLoadCollection(false);
}
}
}
}
/**
* Set the actual underlying list.
*
* This is primarily for the deferred fetching function.
*
*/
@SuppressWarnings("unchecked")
public void setActualList(List> list) {
this.list = (List) list;
}
/**
* Return the actual underlying list.
*/
public List getActualList() {
return list;
}
@Override
public Collection getActualDetails() {
return list;
}
@Override
public Collection> getActualEntries() {
return list;
}
/**
* Return true if the underlying list is populated.
*/
@Override
public boolean isPopulated() {
return list != null;
}
/**
* Return true if this is a reference (lazy loading) bean collection. This is
* the same as !isPopulated();
*/
@Override
public boolean isReference() {
return list == null;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(50);
sb.append("BeanList ");
if (isReadOnly()) {
sb.append("readOnly ");
}
if (list == null) {
sb.append("deferred ");
} else {
sb.append("size[").append(list.size()).append("] ");
sb.append("list").append(list).append("");
}
return sb.toString();
}
/**
* Equal if obj is a List and equal in a list sense.
*
* Specifically obj does not need to be a BeanList but any list. This does not
* use the FindMany, fetchedMaxRows or finishedFetch properties in the equals
* test.
*
*/
@Override
public boolean equals(Object obj) {
init();
return list.equals(obj);
}
@Override
public int hashCode() {
init();
return list.hashCode();
}
// -----------------------------------------------------//
// The additional methods are here
// -----------------------------------------------------//
// -----------------------------------------------------//
// proxy method for List
// -----------------------------------------------------//
@Override
public void add(int index, E element) {
checkReadOnly();
init();
if (modifyAddListening) {
modifyAddition(element);
}
list.add(index, element);
}
@Override
public void addBean(E bean) {
add(bean);
}
@Override
public boolean add(E o) {
checkReadOnly();
init();
if (modifyAddListening) {
if (list.add(o)) {
modifyAddition(o);
return true;
} else {
return false;
}
}
return list.add(o);
}
@Override
public boolean addAll(Collection extends E> c) {
checkReadOnly();
init();
if (modifyAddListening) {
// all elements in c are added (no contains checking)
getModifyHolder().modifyAdditionAll(c);
}
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection extends E> c) {
checkReadOnly();
init();
if (modifyAddListening) {
// all elements in c are added (no contains checking)
getModifyHolder().modifyAdditionAll(c);
}
return list.addAll(index, c);
}
@Override
public void clear() {
checkReadOnly();
// TODO: when clear() and not initialised could be more clever
// and fetch just the Id's
initClear();
if (modifyRemoveListening) {
for (E aList : list) {
getModifyHolder().modifyRemoval(aList);
}
}
list.clear();
}
@Override
public boolean contains(Object o) {
init();
return list.contains(o);
}
@Override
public boolean containsAll(Collection> c) {
init();
return list.containsAll(c);
}
@Override
public E get(int index) {
init();
return list.get(index);
}
@Override
public int indexOf(Object o) {
init();
return list.indexOf(o);
}
@Override
public boolean isEmpty() {
init();
return list.isEmpty();
}
@Override
public Iterator iterator() {
init();
if (isReadOnly()) {
return new ReadOnlyListIterator<>(list.listIterator());
}
if (modifyListening) {
Iterator it = list.iterator();
return new ModifyIterator<>(this, it);
}
return list.iterator();
}
@Override
public int lastIndexOf(Object o) {
init();
return list.lastIndexOf(o);
}
@Override
public ListIterator listIterator() {
init();
if (isReadOnly()) {
return new ReadOnlyListIterator<>(list.listIterator());
}
if (modifyListening) {
ListIterator it = list.listIterator();
return new ModifyListIterator<>(this, it);
}
return list.listIterator();
}
@Override
public ListIterator listIterator(int index) {
init();
if (isReadOnly()) {
return new ReadOnlyListIterator<>(list.listIterator(index));
}
if (modifyListening) {
ListIterator it = list.listIterator(index);
return new ModifyListIterator<>(this, it);
}
return list.listIterator(index);
}
@Override
public void removeBean(E bean) {
if (list.remove(bean)) {
getModifyHolder().modifyRemoval(bean);
}
}
@Override
public E remove(int index) {
checkReadOnly();
init();
if (modifyRemoveListening) {
E o = list.remove(index);
modifyRemoval(o);
return o;
}
return list.remove(index);
}
@Override
public boolean remove(Object o) {
checkReadOnly();
init();
if (modifyRemoveListening) {
boolean isRemove = list.remove(o);
if (isRemove) {
modifyRemoval(o);
}
return isRemove;
}
return list.remove(o);
}
@Override
public boolean removeAll(Collection> beans) {
checkReadOnly();
init();
if (modifyRemoveListening) {
boolean changed = false;
for (Object bean : beans) {
if (list.remove(bean)) {
// register this bean as having been removed
modifyRemoval(bean);
changed = true;
}
}
return changed;
}
return list.removeAll(beans);
}
@Override
public boolean retainAll(Collection> retainBeans) {
checkReadOnly();
init();
if (modifyRemoveListening) {
boolean changed = false;
Iterator it = list.iterator();
while (it.hasNext()) {
Object bean = it.next();
if (!retainBeans.contains(bean)) {
// removing this bean
it.remove();
modifyRemoval(bean);
changed = true;
}
}
return changed;
}
return list.retainAll(retainBeans);
}
@Override
public E set(int index, E element) {
checkReadOnly();
init();
if (modifyListening) {
E o = list.set(index, element);
modifyAddition(element);
modifyRemoval(o);
return o;
}
return list.set(index, element);
}
@Override
public int size() {
init();
return list.size();
}
@Override
public List subList(int fromIndex, int toIndex) {
init();
if (isReadOnly()) {
return Collections.unmodifiableList(list.subList(fromIndex, toIndex));
}
if (modifyListening) {
return new ModifyList<>(this, list.subList(fromIndex, toIndex));
}
return list.subList(fromIndex, toIndex);
}
@Override
public Object[] toArray() {
init();
return list.toArray();
}
@Override
public T[] toArray(T[] a) {
init();
//noinspection SuspiciousToArrayCall
return list.toArray(a);
}
private static class ReadOnlyListIterator implements ListIterator, Serializable {
private static final long serialVersionUID = 3097271091406323699L;
private final ListIterator i;
ReadOnlyListIterator(ListIterator i) {
this.i = i;
}
@Override
public void add(E o) {
throw new IllegalStateException("This collection is in ReadOnly mode");
}
@Override
public void remove() {
throw new IllegalStateException("This collection is in ReadOnly mode");
}
@Override
public void set(E o) {
throw new IllegalStateException("This collection is in ReadOnly mode");
}
@Override
public boolean hasNext() {
return i.hasNext();
}
@Override
public boolean hasPrevious() {
return i.hasPrevious();
}
@Override
public E next() {
return i.next();
}
@Override
public int nextIndex() {
return i.nextIndex();
}
@Override
public E previous() {
return i.previous();
}
@Override
public int previousIndex() {
return i.previousIndex();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy