blob: 2d6ecdee748f9a9f4f9604966ffa10d591f2868a [file] [log] [blame]
/*
* Copyright (c) 2010-2018 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
*/
package org.eclipse.scout.rt.dataobject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Wrapper for a generic list of values of type {@code V} inside a {@link DoEntity} object.
*
* @see DoEntity#doList(String) creator method
*/
public final class DoList<V> extends DoNode<List<V>> implements IDataObject, Iterable<V> {
public DoList() {
this(null, null);
}
protected DoList(String attributeName, Consumer<DoNode<List<V>>> lazyCreate) {
super(attributeName, lazyCreate, new ArrayList<>());
}
public static <V> DoList<V> of(List<V> list) {
DoList<V> doList = new DoList<>();
doList.set(list);
return doList;
}
/**
* @return modifiable list of all items, never {@code null}.
*/
@Override
public List<V> get() {
create(); // DoList needs to be marked as created on first access, since list can be modified using getter
return super.get();
}
/**
* Replaces the internally wrapped list with the specified {@code newValue} list. If {@code newValue} is {@code null},
* an empty list is used instead.
* <p>
* <b>Use a modifiable list implementation if the items should be modified using {@link DoList} methods.</b>
*/
@Override
public void set(List<V> newValue) {
super.set(newValue != null ? newValue : new ArrayList<>());
}
/**
* Returns the element at the specified position in this list.
*/
public V get(int index) {
return get().get(index);
}
/**
* Appends the specified element to the end of this list.
*/
public void add(V item) {
get().add(item);
}
/**
* Appends all of the elements in the specified collection to the end of this list, in the order that they are
* returned by the specified collection's iterator. Does not append any values if {@code items} is null.
*/
public void addAll(Collection<? extends V> items) {
if (items != null) {
get().addAll(items);
}
}
/**
* Appends all of the elements in the specified array to the end of this list, in the order that they are contained in
* the array. Does not append any values if {@code items} is null.
*/
public void addAll(@SuppressWarnings("unchecked") V... items) {
if (items != null) {
addAll(Arrays.asList(items));
}
}
/**
* Removes the element at the specified position in this list.
*
* @return the element previously at the specified position
*/
public V remove(int index) {
return get().remove(index);
}
/**
* Removes the first occurrence of the specified element from this list, if it is present.
*
* @return {@code true} if this list changed as a result of the call
*/
public boolean remove(V item) {
return get().remove(item);
}
/**
* Removes from this list all of its elements that are contained in the specified collection. Does not remove any
* values if {@code items} is null.
*
* @return {@code true} if this list changed as a result of the call
*/
public boolean removeAll(Collection<? extends V> items) {
if (items != null) {
return get().removeAll(items);
}
return false;
}
/**
* Removes from this list all of its elements that are contained in the specified array. Does not remove any values if
* {@code items} is null.
*
* @return {@code true} if this list changed as a result of the call
*/
public boolean removeAll(@SuppressWarnings("unchecked") V... items) {
if (items != null) {
return removeAll(Arrays.asList(items));
}
return false;
}
/**
* Replaces all items in this list with the given collection of new {@code items}. If {@code items} is {@code null},
* the list is cleared without adding any items.
*/
public void updateAll(Collection<? extends V> items) {
clear();
addAll(items);
}
/**
* Replaces all items in this list with the given array of new {@code items}. If {@code items} is {@code null}, the
* list is cleared without adding any items.
*/
public void updateAll(@SuppressWarnings("unchecked") V... items) {
clear();
addAll(items);
}
/**
* Removes all elements from this list.
*/
public void clear() {
if (get().isEmpty()) {
return;
}
get().clear();
}
/**
* Returns first element of this list or {@code null} if list is empty.
*/
public V first() {
return get().size() == 0 ? null : get(0);
}
/**
* Returns last element of this list or {@code null} if list is empty.
*/
public V last() {
return get().size() == 0 ? null : get(get().size() - 1);
}
/**
* @return the number of elements in this list
*/
public int size() {
return get().size();
}
/**
* @return {@code true} if this list contains no elements, else {@code false}.
*/
public boolean isEmpty() {
return get().isEmpty();
}
/**
* @returns a sequential {@code Stream} with this list as its source.
*/
public Stream<V> stream() {
return get().stream();
}
/**
* @returns a possibly parallel {@code Stream} with this list as its source.
*/
public Stream<V> parallelStream() {
return get().parallelStream();
}
@Override
public Iterator<V> iterator() {
return get().iterator();
}
/**
* @return an {@code ListIterator} over the elements in this list.
*/
public ListIterator<V> listIterator() {
return get().listIterator();
}
/**
* Sorts the internal list using {@code comparator} and returns the list.
*/
public List<V> sort(Comparator<V> comparator) {
Collections.sort(get(), comparator);
return get();
}
/**
* @return the first list element which attribute given by the method reference is equal to the given value.
* <code>null</code> is returned if there is no such list element.
*/
public <VALUE> V findFirst(Function<V, DoValue<VALUE>> accessor, VALUE value) {
return findFirst(DoPredicates.eq(accessor, value));
}
/**
* @return the first list element that evaluates to <code>true</code> when applied to the given {@link Predicate}.
* <code>null</code> is returned if there is no such list element.
*/
public V findFirst(Predicate<V> predicate) {
return stream()
.filter(predicate)
.findFirst()
.orElse(null);
}
/**
* @return all list elements which attribute given by the method reference is equal to the given value. An empty list
* is returned if there are no such elements.
*/
public <VALUE> List<V> find(Function<V, DoValue<VALUE>> accessor, VALUE value) {
return find(DoPredicates.eq(accessor, value));
}
/**
* @return all list elements that are evaluating to <code>true</code> when applied to the given {@link Predicate}. An
* empty list is returned if there are no such elements.
*/
public List<V> find(Predicate<V> predicate) {
return stream()
.filter(predicate)
.collect(Collectors.toList());
}
@Override
public String toString() {
return "DoList [m_list=" + get() + " exists=" + exists() + "]";
}
}