/* |
|
* Copyright (c) 2000, 2013, 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</code> |
|
* implementation with characteristics of a hash map. |
|
* <P> |
|
* |
|
* @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 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</CODE> 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</CODE> 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</CODE> 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</CODE> is null. |
|
* @exception NullPointerException if interfaceName is null. |
|
* @exception ClassCastException |
|
* (unchecked exception) Thrown if <CODE>attribute</CODE> is not an |
|
* instance of <CODE>interfaceName</CODE>. |
|
*/ |
|
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</CODE> 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</CODE> is null. |
|
* @exception NullPointerException if interfaceName is null. |
|
* @exception ClassCastException |
|
* (unchecked exception) Thrown if any element of |
|
* <CODE>attributes</CODE> is not an instance of |
|
* <CODE>interfaceName</CODE>. |
|
*/ |
|
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</CODE> is not an instance of |
|
* <CODE>interfaceName</CODE>. |
|
*/ |
|
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 <tt>null</tt> 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 <tt>null</tt> if this attribute set |
|
* does not contain any attribute value in the given attribute |
|
* category. |
|
* |
|
* @throws NullPointerException |
|
* (unchecked exception) Thrown if the <CODE>category</CODE> is null. |
|
* @throws ClassCastException |
|
* (unchecked exception) Thrown if the <CODE>category</CODE> is not a |
|
* {@link java.lang.Class Class} that implements interface {@link |
|
* Attribute Attribute}. |
|
*/ |
|
public Attribute get(Class<?> category) { |
|
return (Attribute) |
|
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 <tt>true</tt> 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</CODE> is null. |
|
* @throws UnmodifiableSetException |
|
* (unchecked exception) Thrown if this attribute set does not support |
|
* the <CODE>add()</CODE> 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</CODE> is null, then |
|
* <CODE>remove()</CODE> does nothing and returns <tt>false</tt>. |
|
* |
|
* @param category Attribute category to be removed from this |
|
* attribute set. |
|
* |
|
* @return <tt>true</tt> 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()</CODE> 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</CODE> is null, then |
|
* <CODE>remove()</CODE> does nothing and returns <tt>false</tt>. |
|
* |
|
* @param attribute Attribute value to be removed from this attribute set. |
|
* |
|
* @return <tt>true</tt> 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()</CODE> operation. |
|
*/ |
|
public boolean remove(Attribute attribute) { |
|
return |
|
attribute != null && |
|
attrMap.remove(attribute.getCategory()) != null; |
|
} |
|
/** |
|
* Returns <tt>true</tt> if this attribute set contains an |
|
* attribute for the specified category. |
|
* |
|
* @param category whose presence in this attribute set is |
|
* to be tested. |
|
* |
|
* @return <tt>true</tt> 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 <tt>true</tt> if this attribute set contains the given |
|
* attribute. |
|
* |
|
* @param attribute value whose presence in this attribute set is |
|
* to be tested. |
|
* |
|
* @return <tt>true</tt> 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)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)</CODE> |
|
* operation is unspecified if the specified set is modified while |
|
* the operation is in progress. |
|
* <P> |
|
* If the <CODE>addAll(AttributeSet)</CODE> 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 <tt>true</tt> if this attribute set changed as a result of the |
|
* call. |
|
* |
|
* @throws UnmodifiableSetException |
|
* (Unchecked exception) Thrown if this attribute set does not |
|
* support the <tt>addAll(AttributeSet)</tt> 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<attrs.length; i++) { |
|
Attribute newValue = |
|
AttributeSetUtilities.verifyAttributeValue(attrs[i], |
|
myInterface); |
|
Object oldValue = attrMap.put(newValue.getCategory(), newValue); |
|
result = (! newValue.equals(oldValue)) || result; |
|
} |
|
return result; |
|
} |
|
/** |
|
* Returns the number of attributes in this attribute set. If this |
|
* attribute set contains more than <tt>Integer.MAX_VALUE</tt> elements, |
|
* returns <tt>Integer.MAX_VALUE</tt>. |
|
* |
|
* @return The number of attributes in this attribute set. |
|
*/ |
|
public int size() { |
|
return attrMap.size(); |
|
} |
|
/** |
|
* |
|
* @return the Attributes contained in this set as an array, zero length |
|
* if the AttributeSet is empty. |
|
*/ |
|
public Attribute[] toArray() { |
|
Attribute []attrs = new Attribute[size()]; |
|
attrMap.values().toArray(attrs); |
|
return attrs; |
|
} |
|
/** |
|
* Removes all attributes from this attribute set. |
|
* |
|
* @throws UnmodifiableSetException |
|
* (unchecked exception) Thrown if this attribute set does not support |
|
* the <CODE>clear()</CODE> operation. |
|
*/ |
|
public void clear() { |
|
attrMap.clear(); |
|
} |
|
/** |
|
* Returns true if this attribute set contains no attributes. |
|
* |
|
* @return true if this attribute set contains no attributes. |
|
*/ |
|
public boolean isEmpty() { |
|
return attrMap.isEmpty(); |
|
} |
|
/** |
|
* Compares the specified object with this attribute set for equality. |
|
* Returns <tt>true</tt> if the given object is also an attribute set and |
|
* the two attribute sets contain the same attribute category-attribute |
|
* value mappings. This ensures that the |
|
* <tt>equals()</tt> method works properly across different |
|
* implementations of the AttributeSet interface. |
|
* |
|
* @param object to be compared for equality with this attribute set. |
|
* |
|
* @return <tt>true</tt> if the specified object is equal to this |
|
* attribute set. |
|
*/ |
|
public boolean equals(Object object) { |
|
if (object == null || !(object instanceof AttributeSet)) { |
|
return false; |
|
} |
|
AttributeSet aset = (AttributeSet)object; |
|
if (aset.size() != size()) { |
|
return false; |
|
} |
|
Attribute[] attrs = toArray(); |
|
for (int i=0;i<attrs.length; i++) { |
|
if (!aset.containsValue(attrs[i])) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
/** |
|
* Returns the hash code value for this attribute set. |
|
* The hash code of an attribute set is defined to be the sum |
|
* of the hash codes of each entry in the AttributeSet. |
|
* This ensures that <tt>t1.equals(t2)</tt> implies that |
|
* <tt>t1.hashCode()==t2.hashCode()</tt> for any two attribute sets |
|
* <tt>t1</tt> and <tt>t2</tt>, as required by the general contract of |
|
* {@link java.lang.Object#hashCode() Object.hashCode()}. |
|
* |
|
* @return The hash code value for this attribute set. |
|
*/ |
|
public int hashCode() { |
|
int hcode = 0; |
|
Attribute[] attrs = toArray(); |
|
for (int i=0;i<attrs.length; i++) { |
|
hcode += attrs[i].hashCode(); |
|
} |
|
return hcode; |
|
} |
|
} |