/* * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.print.attribute; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.HashMap; /** * Class HashAttributeSet provides an {@code AttributeSet} * implementation with characteristics of a hash map. * * @author Alan Kaminsky */ public class HashAttributeSet implements AttributeSet, Serializable { private static final long serialVersionUID = 5311560590283707917L; /** * The interface of which all members of this attribute set must be an * instance. It is assumed to be interface {@link Attribute Attribute} * or a subinterface thereof. * @serial */ private Class myInterface; /* * A HashMap used by the implementation. * The serialised form doesn't include this instance variable. */ private transient HashMap, Attribute> attrMap = new HashMap<>(); /** * Write the instance to a stream (ie serialize the object) * * @serialData * The serialized form of an attribute set explicitly writes the * number of attributes in the set, and each of the attributes. * This does not guarantee equality of serialized forms since * the order in which the attributes are written is not defined. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); Attribute [] attrs = toArray(); s.writeInt(attrs.length); for (int i = 0; i < attrs.length; i++) { s.writeObject(attrs[i]); } } /** * Reconstitute an instance from a stream that is, deserialize it). */ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); attrMap = new HashMap<>(); int count = s.readInt(); Attribute attr; for (int i = 0; i < count; i++) { attr = (Attribute)s.readObject(); add(attr); } } /** * Construct a new, empty attribute set. */ public HashAttributeSet() { this(Attribute.class); } /** * Construct a new attribute set, * initially populated with the given attribute. * * @param attribute Attribute value to add to the set. * * @exception NullPointerException * (unchecked exception) Thrown if {@code attribute} is null. */ public HashAttributeSet(Attribute attribute) { this (attribute, Attribute.class); } /** * Construct a new attribute set, * initially populated with the values from the * given array. The new attribute set is populated by * adding the elements of {@code attributes} array to the set in * sequence, starting at index 0. Thus, later array elements may replace * earlier array elements if the array contains duplicate attribute * values or attribute categories. * * @param attributes Array of attribute values to add to the set. * If null, an empty attribute set is constructed. * * @exception NullPointerException * (unchecked exception) Thrown if any element of * {@code attributes} is null. */ public HashAttributeSet(Attribute[] attributes) { this (attributes, Attribute.class); } /** * Construct a new attribute set, * initially populated with the values from the given set. * * @param attributes Set of attributes from which to initialise this set. * If null, an empty attribute set is constructed. * */ public HashAttributeSet(AttributeSet attributes) { this (attributes, Attribute.class); } /** * Construct a new, empty attribute set, where the members of * the attribute set are restricted to the given interface. * * @param interfaceName The interface of which all members of this * attribute set must be an instance. It is assumed to * be interface {@link Attribute Attribute} or a * subinterface thereof. * @exception NullPointerException if interfaceName is null. */ protected HashAttributeSet(Class interfaceName) { if (interfaceName == null) { throw new NullPointerException("null interface"); } myInterface = interfaceName; } /** * Construct a new attribute set, initially populated with the given * attribute, where the members of the attribute set are restricted to the * given interface. * * @param attribute Attribute value to add to the set. * @param interfaceName The interface of which all members of this * attribute set must be an instance. It is assumed to * be interface {@link Attribute Attribute} or a * subinterface thereof. * * @exception NullPointerException * (unchecked exception) Thrown if {@code attribute} is null. * @exception NullPointerException if interfaceName is null. * @exception ClassCastException * (unchecked exception) Thrown if {@code attribute} is not an * instance of {@code interfaceName}. */ protected HashAttributeSet(Attribute attribute, Class interfaceName) { if (interfaceName == null) { throw new NullPointerException("null interface"); } myInterface = interfaceName; add (attribute); } /** * Construct a new attribute set, where the members of the attribute * set are restricted to the given interface. * The new attribute set is populated * by adding the elements of {@code attributes} array to the set in * sequence, starting at index 0. Thus, later array elements may replace * earlier array elements if the array contains duplicate attribute * values or attribute categories. * * @param attributes Array of attribute values to add to the set. If * null, an empty attribute set is constructed. * @param interfaceName The interface of which all members of this * attribute set must be an instance. It is assumed to * be interface {@link Attribute Attribute} or a * subinterface thereof. * * @exception NullPointerException * (unchecked exception) Thrown if any element of * {@code attributes} is null. * @exception NullPointerException if interfaceName is null. * @exception ClassCastException * (unchecked exception) Thrown if any element of * {@code attributes} is not an instance of * {@code interfaceName}. */ protected HashAttributeSet(Attribute[] attributes, Class interfaceName) { if (interfaceName == null) { throw new NullPointerException("null interface"); } myInterface = interfaceName; int n = attributes == null ? 0 : attributes.length; for (int i = 0; i < n; ++ i) { add (attributes[i]); } } /** * Construct a new attribute set, initially populated with the * values from the given set where the members of the attribute * set are restricted to the given interface. * * @param attributes set of attribute values to initialise the set. If * null, an empty attribute set is constructed. * @param interfaceName The interface of which all members of this * attribute set must be an instance. It is assumed to * be interface {@link Attribute Attribute} or a * subinterface thereof. * * @exception ClassCastException * (unchecked exception) Thrown if any element of * {@code attributes} is not an instance of * {@code interfaceName}. */ protected HashAttributeSet(AttributeSet attributes, Class interfaceName) { myInterface = interfaceName; if (attributes != null) { Attribute[] attribArray = attributes.toArray(); int n = attribArray == null ? 0 : attribArray.length; for (int i = 0; i < n; ++ i) { add (attribArray[i]); } } } /** * Returns the attribute value which this attribute set contains in the * given attribute category. Returns {@code null} if this attribute set * does not contain any attribute value in the given attribute category. * * @param category Attribute category whose associated attribute value * is to be returned. It must be a * {@link java.lang.Class Class} * that implements interface {@link Attribute * Attribute}. * * @return The attribute value in the given attribute category contained * in this attribute set, or {@code null} if this attribute set * does not contain any attribute value in the given attribute * category. * * @throws NullPointerException * (unchecked exception) Thrown if the {@code category} is null. * @throws ClassCastException * (unchecked exception) Thrown if the {@code category} is not a * {@link java.lang.Class Class} that implements interface {@link * Attribute Attribute}. */ public Attribute get(Class category) { return attrMap.get(AttributeSetUtilities. verifyAttributeCategory(category, Attribute.class)); } /** * Adds the specified attribute to this attribute set if it is not * already present, first removing any existing in the same * attribute category as the specified attribute value. * * @param attribute Attribute value to be added to this attribute set. * * @return {@code true} if this attribute set changed as a result of the * call, i.e., the given attribute value was not already a * member of this attribute set. * * @throws NullPointerException * (unchecked exception) Thrown if the {@code attribute} is null. * @throws UnmodifiableSetException * (unchecked exception) Thrown if this attribute set does not support * the {@code add()} operation. */ public boolean add(Attribute attribute) { Object oldAttribute = attrMap.put(attribute.getCategory(), AttributeSetUtilities. verifyAttributeValue(attribute, myInterface)); return (!attribute.equals(oldAttribute)); } /** * Removes any attribute for this category from this attribute set if * present. If {@code category} is null, then * {@code remove()} does nothing and returns {@code false}. * * @param category Attribute category to be removed from this * attribute set. * * @return {@code true} if this attribute set changed as a result of the * call, i.e., the given attribute category had been a member of * this attribute set. * * @throws UnmodifiableSetException * (unchecked exception) Thrown if this attribute set does not * support the {@code remove()} operation. */ public boolean remove(Class category) { return category != null && AttributeSetUtilities. verifyAttributeCategory(category, Attribute.class) != null && attrMap.remove(category) != null; } /** * Removes the specified attribute from this attribute set if * present. If {@code attribute} is null, then * {@code remove()} does nothing and returns {@code false}. * * @param attribute Attribute value to be removed from this attribute set. * * @return {@code true} if this attribute set changed as a result of the * call, i.e., the given attribute value had been a member of * this attribute set. * * @throws UnmodifiableSetException * (unchecked exception) Thrown if this attribute set does not * support the {@code remove()} operation. */ public boolean remove(Attribute attribute) { return attribute != null && attrMap.remove(attribute.getCategory()) != null; } /** * Returns {@code true} if this attribute set contains an * attribute for the specified category. * * @param category whose presence in this attribute set is * to be tested. * * @return {@code true} if this attribute set contains an attribute * value for the specified category. */ public boolean containsKey(Class category) { return category != null && AttributeSetUtilities. verifyAttributeCategory(category, Attribute.class) != null && attrMap.get(category) != null; } /** * Returns {@code true} if this attribute set contains the given * attribute. * * @param attribute value whose presence in this attribute set is * to be tested. * * @return {@code true} if this attribute set contains the given * attribute value. */ public boolean containsValue(Attribute attribute) { return attribute != null && attribute instanceof Attribute && attribute.equals(attrMap.get(attribute.getCategory())); } /** * Adds all of the elements in the specified set to this attribute. * The outcome is the same as if the * {@link #add(Attribute) add(Attribute)} * operation had been applied to this attribute set successively with * each element from the specified set. * The behavior of the {@code addAll(AttributeSet)} * operation is unspecified if the specified set is modified while * the operation is in progress. *

* If the {@code addAll(AttributeSet)} operation throws an exception, * the effect on this attribute set's state is implementation dependent; * elements from the specified set before the point of the exception may * or may not have been added to this attribute set. * * @param attributes whose elements are to be added to this attribute * set. * * @return {@code true} if this attribute set changed as a result of the * call. * * @throws UnmodifiableSetException * (Unchecked exception) Thrown if this attribute set does not * support the {@code addAll(AttributeSet)} method. * @throws NullPointerException * (Unchecked exception) Thrown if some element in the specified * set is null, or the set is null. * * @see #add(Attribute) */ public boolean addAll(AttributeSet attributes) { Attribute []attrs = attributes.toArray(); boolean result = false; for (int i=0; i