blob: b659dcf50d2d31584ed0c587c09803f94bcd68ac [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package javax.swing.text;
26
27import java.util.Hashtable;
28import java.util.Enumeration;
29import java.util.Collections;
30import java.io.IOException;
31import java.io.ObjectInputStream;
32import java.io.ObjectOutputStream;
33import java.io.Serializable;
34
35/**
36 * A straightforward implementation of MutableAttributeSet using a
37 * hash table.
38 * <p>
39 * <strong>Warning:</strong>
40 * Serialized objects of this class will not be compatible with
41 * future Swing releases. The current serialization support is
42 * appropriate for short term storage or RMI between applications running
43 * the same version of Swing. As of 1.4, support for long term storage
44 * of all JavaBeans<sup><font size="-2">TM</font></sup>
45 * has been added to the <code>java.beans</code> package.
46 * Please see {@link java.beans.XMLEncoder}.
47 *
48 * @author Tim Prinzing
49 */
50public class SimpleAttributeSet implements MutableAttributeSet, Serializable, Cloneable
51{
52 private static final long serialVersionUID = -6631553454711782652L;
53
54 /**
55 * An empty attribute set.
56 */
57 public static final AttributeSet EMPTY = new EmptyAttributeSet();
58
59 private transient Hashtable table = new Hashtable(3);
60
61 /**
62 * Creates a new attribute set.
63 */
64 public SimpleAttributeSet() {
65 }
66
67 /**
68 * Creates a new attribute set based on a supplied set of attributes.
69 *
70 * @param source the set of attributes
71 */
72 public SimpleAttributeSet(AttributeSet source) {
73 addAttributes(source);
74 }
75
76 private SimpleAttributeSet(Hashtable table) {
77 this.table = table;
78 }
79
80 /**
81 * Checks whether the set of attributes is empty.
82 *
83 * @return true if the set is empty else false
84 */
85 public boolean isEmpty()
86 {
87 return table.isEmpty();
88 }
89
90 /**
91 * Gets a count of the number of attributes.
92 *
93 * @return the count
94 */
95 public int getAttributeCount() {
96 return table.size();
97 }
98
99 /**
100 * Tells whether a given attribute is defined.
101 *
102 * @param attrName the attribute name
103 * @return true if the attribute is defined
104 */
105 public boolean isDefined(Object attrName) {
106 return table.containsKey(attrName);
107 }
108
109 /**
110 * Compares two attribute sets.
111 *
112 * @param attr the second attribute set
113 * @return true if the sets are equal, false otherwise
114 */
115 public boolean isEqual(AttributeSet attr) {
116 return ((getAttributeCount() == attr.getAttributeCount()) &&
117 containsAttributes(attr));
118 }
119
120 /**
121 * Makes a copy of the attributes.
122 *
123 * @return the copy
124 */
125 public AttributeSet copyAttributes() {
126 return (AttributeSet) clone();
127 }
128
129 /**
130 * Gets the names of the attributes in the set.
131 *
132 * @return the names as an <code>Enumeration</code>
133 */
134 public Enumeration<?> getAttributeNames() {
135 return table.keys();
136 }
137
138 /**
139 * Gets the value of an attribute.
140 *
141 * @param name the attribute name
142 * @return the value
143 */
144 public Object getAttribute(Object name) {
145 Object value = table.get(name);
146 if (value == null) {
147 AttributeSet parent = getResolveParent();
148 if (parent != null) {
149 value = parent.getAttribute(name);
150 }
151 }
152 return value;
153 }
154
155 /**
156 * Checks whether the attribute list contains a
157 * specified attribute name/value pair.
158 *
159 * @param name the name
160 * @param value the value
161 * @return true if the name/value pair is in the list
162 */
163 public boolean containsAttribute(Object name, Object value) {
164 return value.equals(getAttribute(name));
165 }
166
167 /**
168 * Checks whether the attribute list contains all the
169 * specified name/value pairs.
170 *
171 * @param attributes the attribute list
172 * @return true if the list contains all the name/value pairs
173 */
174 public boolean containsAttributes(AttributeSet attributes) {
175 boolean result = true;
176
177 Enumeration names = attributes.getAttributeNames();
178 while (result && names.hasMoreElements()) {
179 Object name = names.nextElement();
180 result = attributes.getAttribute(name).equals(getAttribute(name));
181 }
182
183 return result;
184 }
185
186 /**
187 * Adds an attribute to the list.
188 *
189 * @param name the attribute name
190 * @param value the attribute value
191 */
192 public void addAttribute(Object name, Object value) {
193 table.put(name, value);
194 }
195
196 /**
197 * Adds a set of attributes to the list.
198 *
199 * @param attributes the set of attributes to add
200 */
201 public void addAttributes(AttributeSet attributes) {
202 Enumeration names = attributes.getAttributeNames();
203 while (names.hasMoreElements()) {
204 Object name = names.nextElement();
205 addAttribute(name, attributes.getAttribute(name));
206 }
207 }
208
209 /**
210 * Removes an attribute from the list.
211 *
212 * @param name the attribute name
213 */
214 public void removeAttribute(Object name) {
215 table.remove(name);
216 }
217
218 /**
219 * Removes a set of attributes from the list.
220 *
221 * @param names the set of names to remove
222 */
223 public void removeAttributes(Enumeration<?> names) {
224 while (names.hasMoreElements())
225 removeAttribute(names.nextElement());
226 }
227
228 /**
229 * Removes a set of attributes from the list.
230 *
231 * @param attributes the set of attributes to remove
232 */
233 public void removeAttributes(AttributeSet attributes) {
234 if (attributes == this) {
235 table.clear();
236 }
237 else {
238 Enumeration names = attributes.getAttributeNames();
239 while (names.hasMoreElements()) {
240 Object name = names.nextElement();
241 Object value = attributes.getAttribute(name);
242 if (value.equals(getAttribute(name)))
243 removeAttribute(name);
244 }
245 }
246 }
247
248 /**
249 * Gets the resolving parent. This is the set
250 * of attributes to resolve through if an attribute
251 * isn't defined locally. This is null if there
252 * are no other sets of attributes to resolve
253 * through.
254 *
255 * @return the parent
256 */
257 public AttributeSet getResolveParent() {
258 return (AttributeSet) table.get(StyleConstants.ResolveAttribute);
259 }
260
261 /**
262 * Sets the resolving parent.
263 *
264 * @param parent the parent
265 */
266 public void setResolveParent(AttributeSet parent) {
267 addAttribute(StyleConstants.ResolveAttribute, parent);
268 }
269
270 // --- Object methods ---------------------------------
271
272 /**
273 * Clones a set of attributes.
274 *
275 * @return the new set of attributes
276 */
277 public Object clone() {
278 SimpleAttributeSet attr;
279 try {
280 attr = (SimpleAttributeSet) super.clone();
281 attr.table = (Hashtable) table.clone();
282 } catch (CloneNotSupportedException cnse) {
283 attr = null;
284 }
285 return attr;
286 }
287
288 /**
289 * Returns a hashcode for this set of attributes.
290 * @return a hashcode value for this set of attributes.
291 */
292 public int hashCode() {
293 return table.hashCode();
294 }
295
296 /**
297 * Compares this object to the specified object.
298 * The result is <code>true</code> if the object is an equivalent
299 * set of attributes.
300 * @param obj the object to compare this attribute set with
301 * @return <code>true</code> if the objects are equal;
302 * <code>false</code> otherwise
303 */
304 public boolean equals(Object obj) {
305 if (this == obj) {
306 return true;
307 }
308 if (obj instanceof AttributeSet) {
309 AttributeSet attrs = (AttributeSet) obj;
310 return isEqual(attrs);
311 }
312 return false;
313 }
314
315 /**
316 * Converts the attribute set to a String.
317 *
318 * @return the string
319 */
320 public String toString() {
321 String s = "";
322 Enumeration names = getAttributeNames();
323 while (names.hasMoreElements()) {
324 Object key = names.nextElement();
325 Object value = getAttribute(key);
326 if (value instanceof AttributeSet) {
327 // don't go recursive
328 s = s + key + "=**AttributeSet** ";
329 } else {
330 s = s + key + "=" + value + " ";
331 }
332 }
333 return s;
334 }
335
336 private void writeObject(java.io.ObjectOutputStream s) throws IOException {
337 s.defaultWriteObject();
338 StyleContext.writeAttributeSet(s, this);
339 }
340
341 private void readObject(ObjectInputStream s)
342 throws ClassNotFoundException, IOException {
343 s.defaultReadObject();
344 table = new Hashtable(3);
345 StyleContext.readAttributeSet(s, this);
346 }
347
348 /**
349 * An AttributeSet that is always empty.
350 */
351 static class EmptyAttributeSet implements AttributeSet, Serializable {
352 static final long serialVersionUID = -8714803568785904228L;
353
354 public int getAttributeCount() {
355 return 0;
356 }
357 public boolean isDefined(Object attrName) {
358 return false;
359 }
360 public boolean isEqual(AttributeSet attr) {
361 return (attr.getAttributeCount() == 0);
362 }
363 public AttributeSet copyAttributes() {
364 return this;
365 }
366 public Object getAttribute(Object key) {
367 return null;
368 }
369 public Enumeration getAttributeNames() {
370 return Collections.emptyEnumeration();
371 }
372 public boolean containsAttribute(Object name, Object value) {
373 return false;
374 }
375 public boolean containsAttributes(AttributeSet attributes) {
376 return (attributes.getAttributeCount() == 0);
377 }
378 public AttributeSet getResolveParent() {
379 return null;
380 }
381 public boolean equals(Object obj) {
382 if (this == obj) {
383 return true;
384 }
385 return ((obj instanceof AttributeSet) &&
386 (((AttributeSet)obj).getAttributeCount() == 0));
387 }
388 public int hashCode() {
389 return 0;
390 }
391 }
392}