Generics Java

/*
 * XAdES4j - A Java library for generation and verification of XAdES signatures.
 * Copyright (C) 2010 Luis Goncalves.
 *
 * XAdES4j 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 any later version.
 *
 * XAdES4j 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 XAdES4j. If not, see .
 */
//package xades4j.utils;
//import xades4j.properties.PropertyTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
 * A generic bag of properties used to store properties that apply to a specific
 * target (data object descriptions, signature properties collector, signed data
 * objects). The properties are organized by type (class).
 * 
 * @author Luís
 */
public class PropertiesSet
{
    private final Map> properties;
    /**
     * Initializes the property bag with the given initial diferent property types.
     * @param initialNPropTypes the initial number of different property types.
     */
    public PropertiesSet(int initialNPropTypes)
    {
        this.properties = new HashMap>(initialNPropTypes);
    }
    /**
     * Puts a property in the bag. The put operation doesn't allow repeated
     * property types. If a property of this type was previously added an exception
     * is thrown.
     *
     * @param prop the property
     *
     * @throws NullPointerException if {@code prop} is {@code null}
     * @throws PropertyTargetException if a property of this type was previously
     *                              added
     */
    public void put(T prop)
    {
        if (null == prop)
            throw new NullPointerException("Property cannot be null");
        // If an entry for the property's type is already present it means that a
        // property of this type was previously added. Adding another property of
        // this type is not allowed.
        if (properties.containsKey(prop.getClass()))
            throw new Exception(String.format("A property of type %s was already added", prop.getClass().getSimpleName()));
        add(prop);
    }
    /**
     * Adds a property to the bag. The add operation allows multiple properties
     * of the same type but not repeated instances.
     * @param prop the property
     *
     * @throws NullPointerException if {@code prop} is {@code null}
     * @throws PropertyTargetException if the given property (instance)
     *                                      is already present in the bag
     */
    public void add(T prop)
    {
        if (null == prop)
            throw new NullPointerException("Property cannot be null");
        Set propsOfCurrType = properties.get(prop.getClass());
        if (null == propsOfCurrType)
        {
            // No properties of this type have been added.
            propsOfCurrType = new HashSet(1);
            properties.put(prop.getClass(), propsOfCurrType);
        }
        // Repeated instances are not allowed.
        if (!propsOfCurrType.add(prop))
            throw new Exception("Property instance already present");
    }
    /**
     * Removes a property from the bag.
     *
     * @param prop the property to be removed
     *
     * @throws NullPointerException if the property is {@code null}
     * @throws IllegalStateException if the property is not present
     */
    public void remove(T prop)
    {
        if (null == prop)
            throw new NullPointerException("Property cannot be null");
        Set propsOfCurrType = properties.get(prop.getClass());
        if (null == propsOfCurrType || !propsOfCurrType.remove(prop))
            throw new IllegalStateException("Property not present");
        if (propsOfCurrType.isEmpty())
            properties.remove(prop.getClass());
    }
    /**
     * Indicates whether the bag has any properties.
     * @return {@code true} if the bag has no properties
     */
    public boolean isEmpty()
    {
        // If any entry for any property type is present, then at least one
        // property was specified.
        return properties.isEmpty();
    }
    /**
     * Gets the properties in the bag.
     * @return un unmodifiable collection of properties
     */
    public Collection getProperties()
    {
        if (properties.isEmpty())
            return Collections.emptyList();
        Collection props = new ArrayList(properties.size() + 3);
        for (Set propsOfType : properties.values())
        {
            props.addAll(propsOfType);
        }
        return props;
    }
}