001 /* HashAttributeSet.java --
002 Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038 package javax.print.attribute;
039
040 import java.io.IOException;
041 import java.io.ObjectInputStream;
042 import java.io.ObjectOutputStream;
043 import java.io.Serializable;
044 import java.util.HashMap;
045 import java.util.Iterator;
046
047 /**
048 * <code>HashAttributeSet</code> provides an implementation of
049 * {@link javax.print.attribute.AttributeSet}.
050 */
051 public class HashAttributeSet implements AttributeSet, Serializable
052 {
053 private static final long serialVersionUID = 5311560590283707917L;
054
055 private Class myInterface;
056 private transient HashMap attributeMap = new HashMap();
057
058 /**
059 * Creates an empty <code>HashAttributeSet</code> object.
060 */
061 public HashAttributeSet()
062 {
063 this(Attribute.class);
064 }
065
066 /**
067 * Creates a <code>HashAttributeSet</code> object with the given
068 * attribute in it.
069 *
070 * @param attribute the attribute to put into the set
071 *
072 * @exception NullPointerException if attribute is null
073 */
074 public HashAttributeSet(Attribute attribute)
075 {
076 this(attribute, Attribute.class);
077 }
078
079 /**
080 * Creates a <code>HashAttributeSet</code> object with the given
081 * attributes in it.
082 *
083 * @param attributes the array of attributes to put into the set. If
084 * <code>null</code> an empty set is created.
085 *
086 * @exception NullPointerException if one of the attributes of the given
087 * array is null.
088 */
089 public HashAttributeSet(Attribute[] attributes)
090 {
091 this(attributes, Attribute.class);
092 }
093
094 /**
095 * Creates a <code>HashAttributeSet</code> object with attributes
096 * of the given attributes set in it.
097 *
098 * @param attributes the attributes set to put into the set. If
099 * <code>null</code> an empty set is created.
100 */
101 public HashAttributeSet(AttributeSet attributes)
102 {
103 this(attributes, Attribute.class);
104 }
105
106 /**
107 * Creates an empty <code>HashAttributeSet</code> object.
108 *
109 * @param interfaceName the interface that all members must implement
110 *
111 * @exception NullPointerException if interfaceName is null
112 */
113 protected HashAttributeSet(Class<?> interfaceName)
114 {
115 if (interfaceName == null)
116 throw new NullPointerException("interfaceName may not be null");
117
118 myInterface = interfaceName;
119 }
120
121 /**
122 * Creates a <code>HashAttributeSet</code> object with the given
123 * attribute in it.
124 *
125 * @param attribute the attribute to put into the set.
126 * @param interfaceName the interface that all members must implement.
127 *
128 * @exception ClassCastException if attribute is not an interface of
129 * interfaceName
130 * @exception NullPointerException if attribute or interfaceName is null
131 */
132 protected HashAttributeSet(Attribute attribute, Class<?> interfaceName)
133 {
134 this(interfaceName);
135
136 if (attribute == null)
137 throw new NullPointerException();
138
139 addInternal(attribute, interfaceName);
140 }
141
142 /**
143 * Creates a <code>HashAttributeSet</code> object with the given
144 * attributes in it.
145 *
146 * @param attributes the array of attributes to put into the set. If
147 * <code>null</code> an empty set is created.
148 * @param interfaceName the interface that all members must implement.
149 *
150 * @exception ClassCastException if any element of attributes is not an
151 * interface of interfaceName
152 * @exception NullPointerException if attributes or interfaceName is null
153 */
154 protected HashAttributeSet(Attribute[] attributes, Class<?> interfaceName)
155 {
156 this(interfaceName);
157
158 if (attributes != null)
159 {
160 for (int index = 0; index < attributes.length; index++)
161 addInternal(attributes[index], interfaceName);
162 }
163 }
164
165 /**
166 * Creates a <code>HashAttributeSet</code> object with attributes
167 * of the given attributes set in it.
168 *
169 * @param attributes the attributes set to put into the set. If
170 * <code>null</code> an empty set is created.
171 * @param interfaceName the interface that all members must implement.
172 *
173 * @exception ClassCastException if any element of attributes is not an
174 * interface of interfaceName
175 */
176 protected HashAttributeSet(AttributeSet attributes, Class<?> interfaceName)
177 {
178 this(interfaceName);
179
180 if (attributes != null)
181 addAllInternal(attributes, interfaceName);
182 }
183
184 /**
185 * Adds the specified attribute value to this attribute set
186 * if it is not already present.
187 *
188 * This operation removes any existing attribute of the same category
189 * before adding the given attribute to the set.
190 *
191 * @param attribute the attribute to add.
192 * @return <code>true</code> if the set is changed, false otherwise.
193 * @throws NullPointerException if the attribute is <code>null</code>.
194 * @throws UnmodifiableSetException if the set does not support modification.
195 */
196 public boolean add(Attribute attribute)
197 {
198 return addInternal(attribute, myInterface);
199 }
200
201 private boolean addInternal(Attribute attribute, Class interfaceName)
202 {
203 if (attribute == null)
204 throw new NullPointerException("attribute may not be null");
205
206 AttributeSetUtilities.verifyAttributeCategory(interfaceName,
207 myInterface);
208
209 Object old = attributeMap.put
210 (attribute.getCategory(), AttributeSetUtilities.verifyAttributeValue
211 (attribute, interfaceName));
212 return !attribute.equals(old);
213 }
214
215 /**
216 * Adds all of the elements in the specified set to this attribute set.
217 *
218 * @param attributes the set of attributes to add.
219 * @return <code>true</code> if the set is changed, false otherwise.
220 * @throws UnmodifiableSetException if the set does not support modification.
221 *
222 * @see #add(Attribute)
223 */
224 public boolean addAll(AttributeSet attributes)
225 {
226 return addAllInternal(attributes, myInterface);
227 }
228
229 private boolean addAllInternal(AttributeSet attributes, Class interfaceName)
230 {
231 boolean modified = false;
232 Attribute[] array = attributes.toArray();
233
234 for (int index = 0; index < array.length; index++)
235 if (addInternal(array[index], interfaceName))
236 modified = true;
237
238 return modified;
239 }
240
241 /**
242 * Removes all attributes from this attribute set.
243 *
244 * @throws UnmodifiableSetException if the set does not support modification.
245 */
246 public void clear()
247 {
248 attributeMap.clear();
249 }
250
251 /**
252 * Checks if this attributes set contains an attribute with the given
253 * category.
254 *
255 * @param category the category to test for.
256 * @return <code>true</code> if an attribute of the category is contained
257 * in the set, <code>false</code> otherwise.
258 */
259 public boolean containsKey(Class<?> category)
260 {
261 return attributeMap.containsKey(category);
262 }
263
264 /**
265 * Checks if this attribute set contains the given attribute.
266 *
267 * @param attribute the attribute to test for.
268 * @return <code>true</code> if the attribute is contained in the set,
269 * <code>false</code> otherwise.
270 */
271 public boolean containsValue(Attribute attribute)
272 {
273 return attributeMap.containsValue(attribute);
274 }
275
276 /**
277 * Tests this set for equality with the given object. <code>true</code> is
278 * returned, if the given object is also of type <code>AttributeSet</code>
279 * and the contained attributes are the same as in this set.
280 *
281 * @param obj the Object to test.
282 * @return <code>true</code> if equal, false otherwise.
283 */
284 public boolean equals(Object obj)
285 {
286 if (! (obj instanceof HashAttributeSet))
287 return false;
288
289 return attributeMap.equals(((HashAttributeSet) obj).attributeMap);
290 }
291
292 /**
293 * Returns the attribute object contained in this set for the given attribute
294 * category.
295 *
296 * @param category the category of the attribute. A <code>Class</code>
297 * instance of a class implementing the <code>Attribute</code> interface.
298 * @return The attribute for this category or <code>null</code> if no
299 * attribute is contained for the given category.
300 * @throws NullPointerException if category is null.
301 * @throws ClassCastException if category is not implementing
302 * <code>Attribute</code>.
303 */
304 public Attribute get(Class<?> category)
305 {
306 if (category == null)
307 throw new NullPointerException("category may not be null");
308
309 return (Attribute) attributeMap.get(category);
310 }
311
312 /**
313 * Returns the hashcode value. The hashcode value is the sum of all hashcodes
314 * of the attributes contained in this set.
315 *
316 * @return The hashcode for this attribute set.
317 */
318 public int hashCode()
319 {
320 int hashcode = 0;
321 Iterator it = attributeMap.values().iterator();
322 while (it.hasNext())
323 hashcode = hashcode + it.next().hashCode();
324
325 return hashcode;
326 }
327
328 /**
329 * Checks if the attribute set is empty.
330 *
331 * @return <code>true</code> if the attribute set is empty, false otherwise.
332 */
333 public boolean isEmpty()
334 {
335 return attributeMap.isEmpty();
336 }
337
338 /**
339 * Removes the given attribute from the set. If the given attribute is <code>null</code>
340 * nothing is done and <code>false</code> is returned.
341 *
342 * @param attribute the attribute to remove.
343 * @return <code>true</code> if removed, false in all other cases.
344 * @throws UnmodifiableSetException if the set does not support modification.
345 */
346 public boolean remove(Attribute attribute)
347 {
348 if (attribute == null)
349 return false;
350
351 return attributeMap.remove(attribute.getCategory()) != null;
352 }
353
354 /**
355 * Removes the attribute entry of the given category from the set. If the given
356 * category is <code>null</code> nothing is done and <code>false</code> is returned.
357 *
358 * @param category the category of the entry to be removed.
359 * @return <code>true</code> if an attribute is removed, false in all other cases.
360 * @throws UnmodifiableSetException if the set does not support modification.
361 */
362 public boolean remove(Class<?> category)
363 {
364 if (category == null)
365 return false;
366
367 return attributeMap.remove(category) != null;
368 }
369
370 /**
371 * Returns the number of elements in this attribute set.
372 *
373 * @return The number of elements.
374 */
375 public int size()
376 {
377 return attributeMap.size();
378 }
379
380 /**
381 * Returns the content of the attribute set as an array
382 *
383 * @return An array of attributes.
384 */
385 public Attribute[] toArray()
386 {
387 int index = 0;
388 Iterator it = attributeMap.values().iterator();
389 Attribute[] array = new Attribute[size()];
390
391 while (it.hasNext())
392 {
393 array[index] = (Attribute) it.next();
394 index++;
395 }
396
397 return array;
398 }
399
400 // Implemented as specified in serialized form
401 private void readObject(ObjectInputStream s)
402 throws ClassNotFoundException, IOException
403 {
404 myInterface = (Class) s.readObject();
405 int size = s.readInt();
406 attributeMap = new HashMap(size);
407 for (int i=0; i < size; i++)
408 add((Attribute) s.readObject());
409 }
410
411 private void writeObject(ObjectOutputStream s) throws IOException
412 {
413 s.writeObject(myInterface);
414 s.writeInt(size());
415 Iterator it = attributeMap.values().iterator();
416 while (it.hasNext())
417 s.writeObject(it.next());
418 }
419 }