package eu.dnetlib.dlms.union.objects;

import java.util.HashSet;

import eu.dnetlib.dlms.lowlevel.LowLevelException;
import eu.dnetlib.dlms.lowlevel.objects.Set;
import eu.dnetlib.dlms.union.types.UnionSetType;
import eu.dnetlib.dlms.union.types.UnionType;

/**
 * Set extension for Unions. A UnionSet is a container for objects belonging already to specified Sets. Those Sets are
 * the ones in UnionSet.sets collection. UnionSets hold references to their objects using Wrapper instances. Removing an
 * object from a UnionSet does not affect the original object, while deleting the original object will cause the
 * deletion of its corresponding object in UnionSet.
 * 
 * @see eu.dnetlib.dlms.lowlevel.objects.Wrapper
 * @author lexis
 */
public class UnionSet extends Set {

	/**
	 * java.util.Set of the Sets whose objects can be included in this union. Set collection is used to automatically
	 * avoid duplicate entries.
	 */
	private java.util.Set<Set> sets;

	public void setSets(final java.util.Set<Set> sets) {
		this.sets = sets;
	}

	public java.util.Set<Set> getSets() {
		return this.sets;
	}

	/**
	 * Constructor.
	 */
	public UnionSet() {
		super();
		this.sets = new HashSet<Set>();
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.dlms.lowlevel.objects.Set#getType()
	 */
	@Override
	public UnionType getType() {
		return (UnionType) super.getType();
	}

	/**
	 * Adds a Set to the sets included in this union. If the collection is null, then it is initialized before the
	 * element is added. A LowLevelException is thrown if the given Set has a SetType whose not declared in this
	 * setType.
	 * 
	 * @param set
	 *            Set instance
	 */
	public void addSet(final Set set) {
		if (this.sets == null)
			this.sets = new HashSet<Set>();
		if (this.getObjectType().getSetTypes().contains(set.getObjectType()))
			this.sets.add(set);
		else
			throw new LowLevelException("Set " + set.getName() + ", id " + set.getId() + " is not allowed in UnionSet " + this.getName() + ", id "
					+ this.getId());
	}

	/**
	 * Removes the Set from the collection of sets in this Union. Does nothing if sets is null or if it was not included
	 * in the union. Throws exception if this set is not empty
	 * 
	 * @param set
	 *            Set to remove from sets collection
	 */
	public void removeSet(final Set set) {
		if (this.getObjects().isEmpty()) {
			if (this.sets != null)
				this.sets.remove(set);
		} else
			throw new LowLevelException("Cannot remove Sets from a non-empty UnionSet");
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see eu.dnetlib.dlms.lowlevel.objects.Set#getObjectType()
	 */
	@Override
	public UnionSetType getObjectType() {
		return (UnionSetType) super.getObjectType();
	}

}
