/*
* Copyright (c) 2010 Ecole des Mines de Nantes.
*
* This file is part of Entropy.
*
* Entropy is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Entropy is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Entropy. If not, see <http://www.gnu.org/licenses/>.
*/
package entropy.configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ListIterator;
/**
* A set of ManagedElement.
* <p/>
* TODO: Check if there is no more add* methods to override to avoid multiple addition of a same element.
* FIXME: Behavior fix optional fields
*
* @param <E> The subclass of ManagedElements contained in the set
* @author Fabien Hermenier
*/
public class DefaultManagedElementSet<E extends ManagedElement> extends ArrayList<E> implements ManagedElementSet<E> {
private HashMap<String, E> map;
/**
* Default serial UID.
*/
private static final long serialVersionUID = 1L;
/**
* Create a new empty set.
*/
public DefaultManagedElementSet() {
super();
map = new HashMap<String, E>();
}
/**
* Make a set with a first element in it.
*
* @param elem the element to add
*/
public DefaultManagedElementSet(final E elem) {
this();
this.add(elem);
}
/**
* Copy constructor.
*
* @param ref the reference
*/
public DefaultManagedElementSet(final ManagedElementSet<E> ref) {
this();
this.addAll(ref);
//super(ref);
}
/**
* Retrieve a element from its identifier.
*
* @param id The identifier of the element
* @return The element or null if it is not in the set
*/
@Override
public E get(String id) {
return map.get(id);
}
/**
* Merge this current list with a other list.
*
* @param elements the other list
* @return true is the current list has changed, false otherwise
*/
@Override
public boolean addAll(ManagedElementSet<E> elements) {
boolean changed = false;
for (E e : elements) {
if (this.add(e)) {
changed = true;
}
}
return changed;
}
/**
* Add a new element.
* The element is added iff there is no already an element with the same name in the list.
*
* @param e The element to add
* @return true if the element is added.
*/
@Override
public final boolean add(E e) {
if (map.containsKey(e.getName())) {
return false;
}
map.put(e.getName(), e);
return super.add(e);
}
/**
* Test the equality between two object.
*
* @param o The object to compare with
* @return true if o is an instance of ManagedElementSet and if all the element of each set
* is contained into the other.
*/
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
} else if (o == this) {
return true;
} else if (o instanceof ManagedElementSet) {
//Cannot use super.equals() has we do not consider ordering
ManagedElementSet<E> ref = (ManagedElementSet<E>) o;
if (ref.size() != this.size()) {
return false;
}
for (E e : ref) {
if (!contains(e)) {
return false;
}
}
return true;
}
return false;
}
@Override
public int hashCode() {
int hashCode = 1;
for (E obj : this) {
hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
}
return hashCode;
}
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("{");
for (ListIterator<E> li = this.listIterator(); li.hasNext();) {
buffer.append(li.next().getName());
if (li.hasNext()) {
buffer.append(", ");
}
}
buffer.append("}");
return buffer.toString();
}
/**
* Check if an element is in a set or not.
*
* @param e the element to look for
* @return {@code true} if the element is in the set
*/
@Override
public boolean contains(E e) {
return map.containsKey(e.getName());
}
/**
* Remove an element for the set.
*
* @param o the element to remove
* @return {@code true} if the element is removed
*/
@Override
public boolean remove(E o) {
if (super.remove(o)) {
map.remove(o.getName());
return true;
}
return false;
}
@Override
public E remove(int i) {
E e = super.remove(i);
if (e != null) {
map.remove(e.getName());
}
return e;
}
@Override
public void clear() {
super.clear();
map.clear();
}
@Override
public boolean containsAll(ManagedElementSet<E> elems) {
for (E e : elems) {
if (!this.contains(e)) {
return false;
}
}
return true;
}
@Override
public boolean removeAll(ManagedElementSet<E> elems) {
boolean changed = false;
for (E e : elems) {
changed |= remove(e);
}
return changed;
}
@Override
public boolean retainAll(ManagedElementSet<E> elems) {
int i = 0;
boolean ret = false;
while (i < size()) {
E o = get(i);
if (!elems.contains(o)) {
remove(o);
ret = true;
} else {
i++;
}
}
return ret;
}
@Override
public ManagedElementSet<E> clone() {
return new DefaultManagedElementSet<E>(this);
}
}