/*
** 2014 September 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
*/
package info.ata4.util.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
/**
*
* @author Nico Bergemann <barracuda415 at yahoo.de>
* @param <T>
*/
public class Node<T> implements Collection<Node<T>> {
private T data;
private Node<T> parent;
private final List<Node<T>> children = new ArrayList<>();
public Node() {
}
public Node(T data) {
this.data = data;
}
public Node(Collection<Node<T>> children) {
if (children != null) {
this.children.addAll(children);
}
}
public Node(T data, Collection<Node<T>> children) {
this.data = data;
if (children != null) {
this.children.addAll(children);
}
}
public T data() {
return data;
}
public void data(T data) {
this.data = data;
}
public Node<T> parent() {
return parent;
}
private void parent(Node<T> parent) {
this.parent = parent;
}
public void forEachData(Consumer<T> action) {
Objects.requireNonNull(action);
action.accept(data());
children.forEach(node -> node.forEachData(action));
}
@Override
public int size() {
return children.size();
}
@Override
public boolean isEmpty() {
return children.isEmpty();
}
@Override
public boolean contains(Object o) {
return children.contains(o);
}
@Override
public Iterator<Node<T>> iterator() {
return Collections.unmodifiableList(children).iterator();
}
@Override
public Spliterator<Node<T>> spliterator() {
return Spliterators.spliterator(Collections.unmodifiableList(children),
Spliterator.ORDERED | Spliterator.IMMUTABLE);
}
@Override
public Object[] toArray() {
return children.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return children.toArray(a);
}
@Override
public boolean add(Node<T> node) {
boolean added = children.add(node);
if (added) {
node.parent(this);
}
return added;
}
@Override
public boolean remove(Object o) {
boolean removed = children.remove(o);
if (removed) {
((Node<T>) o).parent(null);
}
return removed;
}
@Override
public boolean containsAll(Collection<?> c) {
return children.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends Node<T>> c) {
boolean added = children.addAll(c);
if (added) {
forEach(node -> node.parent(this));
}
return added;
}
@Override
public boolean removeAll(Collection<?> c) {
List<Node<T>> childrenOld = new ArrayList<>(children);
boolean removed = children.removeAll(c);
if (removed) {
childrenOld.removeAll(children);
childrenOld.forEach(node -> node.parent(null));
}
return removed;
}
@Override
public boolean retainAll(Collection<?> c) {
List<Node<T>> childrenOld = new ArrayList<>(children);
boolean retained = children.retainAll(c);
if (retained) {
childrenOld.removeAll(children);
childrenOld.forEach(node -> node.parent(null));
}
return retained;
}
@Override
public void clear() {
children.clear();
}
@Override
public int hashCode() {
int hash = 5;
hash = 43 * hash + Objects.hashCode(this.data);
hash = 43 * hash + Objects.hashCode(this.children);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Node<?> other = (Node<?>) obj;
if (!Objects.equals(this.data, other.data)) {
return false;
}
if (!Objects.equals(this.children, other.children)) {
return false;
}
return true;
}
}