/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
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;
}
}