1. /*
  2. * @(#)SimpleAttributeSet.java 1.29 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.text;
  8. import java.util.Hashtable;
  9. import java.util.Enumeration;
  10. import java.io.IOException;
  11. import java.io.ObjectInputStream;
  12. import java.io.ObjectOutputStream;
  13. import java.io.Serializable;
  14. import javax.swing.tree.DefaultMutableTreeNode;
  15. /**
  16. * A straightforward implementation of MutableAttributeSet using a
  17. * hash table.
  18. * <p>
  19. * <strong>Warning:</strong>
  20. * Serialized objects of this class will not be compatible with
  21. * future Swing releases. The current serialization support is appropriate
  22. * for short term storage or RMI between applications running the same
  23. * version of Swing. A future release of Swing will provide support for
  24. * long term persistence.
  25. *
  26. * @version 1.29 11/29/01
  27. * @author Tim Prinzing
  28. */
  29. public class SimpleAttributeSet implements MutableAttributeSet, Serializable, Cloneable
  30. {
  31. /**
  32. * An empty attribute set.
  33. */
  34. public static final AttributeSet EMPTY = new EmptyAttributeSet();
  35. private transient Hashtable table = new Hashtable(3);
  36. /**
  37. * Creates a new attribute set.
  38. */
  39. public SimpleAttributeSet() {
  40. }
  41. /**
  42. * Creates a new attribute set based on a supplied set of attributes.
  43. *
  44. * @param source the set of attributes
  45. */
  46. public SimpleAttributeSet(AttributeSet source) {
  47. addAttributes(source);
  48. }
  49. private SimpleAttributeSet(Hashtable table) {
  50. this.table = table;
  51. }
  52. /**
  53. * Checks whether the set of attributes is empty.
  54. *
  55. * @return true if the set is empty else false
  56. */
  57. public boolean isEmpty()
  58. {
  59. return table.isEmpty();
  60. }
  61. /**
  62. * Gets a count of the number of attributes.
  63. *
  64. * @return the count
  65. */
  66. public int getAttributeCount() {
  67. return table.size();
  68. }
  69. /**
  70. * Tells whether a given attribute is defined.
  71. *
  72. * @param attrName the attribute name
  73. * @return true if the attribute is defined
  74. */
  75. public boolean isDefined(Object attrName) {
  76. return table.containsKey(attrName);
  77. }
  78. /**
  79. * Compares two attribute sets.
  80. *
  81. * @param attr the second attribute set
  82. * @return true if equathe listl
  83. */
  84. public boolean isEqual(AttributeSet attr) {
  85. return ((getAttributeCount() == attr.getAttributeCount()) &&
  86. containsAttributes(attr));
  87. }
  88. /**
  89. * Makes a copy of the attributes.
  90. *
  91. * @return the copy
  92. */
  93. public AttributeSet copyAttributes() {
  94. return (AttributeSet) clone();
  95. }
  96. /**
  97. * Gets the names of the attributes in the set.
  98. *
  99. * @return the names as an Enumeration
  100. */
  101. public Enumeration getAttributeNames() {
  102. return table.keys();
  103. }
  104. /**
  105. * Gets the value of an attribute.
  106. *
  107. * @param name the attribute name
  108. * @return the value
  109. */
  110. public Object getAttribute(Object name) {
  111. Object value = table.get(name);
  112. if (value == null) {
  113. AttributeSet parent = getResolveParent();
  114. if (parent != null) {
  115. value = parent.getAttribute(name);
  116. }
  117. }
  118. return value;
  119. }
  120. /**
  121. * Checks whether the attribute list contains a
  122. * specified attribute name/value pair.
  123. *
  124. * @param name the name
  125. * @param value the value
  126. * @return true if the name/value pair is in the list
  127. */
  128. public boolean containsAttribute(Object name, Object value) {
  129. return value.equals(getAttribute(name));
  130. }
  131. /**
  132. * Checks whether the attribute list contains all the
  133. * specified name/value pairs.
  134. *
  135. * @param attributes the attribute list
  136. * @return true if the list contains all the name/value pairs
  137. */
  138. public boolean containsAttributes(AttributeSet attributes) {
  139. boolean result = true;
  140. Enumeration names = attributes.getAttributeNames();
  141. while (result && names.hasMoreElements()) {
  142. Object name = names.nextElement();
  143. result = attributes.getAttribute(name).equals(getAttribute(name));
  144. }
  145. return result;
  146. }
  147. /**
  148. * Adds an attribute to the list.
  149. *
  150. * @param name the attribute name
  151. * @param value the attribute value
  152. */
  153. public void addAttribute(Object name, Object value) {
  154. table.put(name, value);
  155. }
  156. /**
  157. * Adds a set of attributes to the list.
  158. *
  159. * @param attributes the set of attributes to add
  160. */
  161. public void addAttributes(AttributeSet attributes) {
  162. Enumeration names = attributes.getAttributeNames();
  163. while (names.hasMoreElements()) {
  164. Object name = names.nextElement();
  165. addAttribute(name, attributes.getAttribute(name));
  166. }
  167. }
  168. /**
  169. * Removes an attribute from the list.
  170. *
  171. * @param name the attribute name
  172. */
  173. public void removeAttribute(Object name) {
  174. table.remove(name);
  175. }
  176. /**
  177. * Removes a set of attributes from the list.
  178. *
  179. * @param names the set of names to remove
  180. */
  181. public void removeAttributes(Enumeration names) {
  182. while (names.hasMoreElements())
  183. removeAttribute(names.nextElement());
  184. }
  185. /**
  186. * Removes a set of attributes from the list.
  187. *
  188. * @param attributes the set of attributes to remove
  189. */
  190. public void removeAttributes(AttributeSet attributes) {
  191. Enumeration names = attributes.getAttributeNames();
  192. while (names.hasMoreElements()) {
  193. Object name = names.nextElement();
  194. Object value = attributes.getAttribute(name);
  195. if (value.equals(getAttribute(name)))
  196. removeAttribute(name);
  197. }
  198. }
  199. /**
  200. * Gets the resolving parent. This is the set
  201. * of attributes to resolve through if an attribute
  202. * isn't defined locally. This is null if there
  203. * are no other sets of attributes to resolve
  204. * through.
  205. *
  206. * @return the parent
  207. */
  208. public AttributeSet getResolveParent() {
  209. return (AttributeSet) table.get(StyleConstants.ResolveAttribute);
  210. }
  211. /**
  212. * Sets the resolving parent.
  213. *
  214. * @param parent the parent
  215. */
  216. public void setResolveParent(AttributeSet parent) {
  217. addAttribute(StyleConstants.ResolveAttribute, parent);
  218. }
  219. // --- Object methods ---------------------------------
  220. /**
  221. * Clones a set of attributes.
  222. *
  223. * @return the new set of attributes
  224. */
  225. public Object clone() {
  226. SimpleAttributeSet attr;
  227. try {
  228. attr = (SimpleAttributeSet) super.clone();
  229. attr.table = (Hashtable) table.clone();
  230. } catch (CloneNotSupportedException cnse) {
  231. attr = null;
  232. }
  233. return attr;
  234. }
  235. /**
  236. * Returns a hashcode for this set of attributes.
  237. * @return a hashcode value for this set of attributes.
  238. */
  239. public int hashCode() {
  240. return table.hashCode();
  241. }
  242. /**
  243. * Compares this object to the specifed object.
  244. * The result is <code>true</code> if and only if the argument is not
  245. * <code>null</code> and is a <code>Font</code> object with the same
  246. * name, style, and point size as this font.
  247. * @param obj the object to compare this font with.
  248. * @return <code>true</code> if the objects are equal;
  249. * <code>false</code> otherwise.
  250. */
  251. public boolean equals(Object obj) {
  252. if (this == obj) {
  253. return true;
  254. }
  255. if (obj instanceof AttributeSet) {
  256. AttributeSet attrs = (AttributeSet) obj;
  257. return isEqual(attrs);
  258. }
  259. return false;
  260. }
  261. /**
  262. * Converts the attribute set to a String.
  263. *
  264. * @return the string
  265. */
  266. public String toString() {
  267. String s = "";
  268. Enumeration names = getAttributeNames();
  269. while (names.hasMoreElements()) {
  270. Object key = names.nextElement();
  271. Object value = getAttribute(key);
  272. if (value instanceof AttributeSet) {
  273. // don't go recursive
  274. s = s + key + "=**AttributeSet** ";
  275. } else {
  276. s = s + key + "=" + value + " ";
  277. }
  278. }
  279. return s;
  280. }
  281. private void writeObject(java.io.ObjectOutputStream s) throws IOException {
  282. s.defaultWriteObject();
  283. StyleContext.writeAttributeSet(s, this);
  284. }
  285. private void readObject(ObjectInputStream s)
  286. throws ClassNotFoundException, IOException {
  287. s.defaultReadObject();
  288. table = new Hashtable(3);
  289. StyleContext.readAttributeSet(s, this);
  290. }
  291. /**
  292. * An AttributeSet this is always empty.
  293. */
  294. static class EmptyAttributeSet implements AttributeSet, Serializable {
  295. public int getAttributeCount() {
  296. return 0;
  297. }
  298. public boolean isDefined(Object attrName) {
  299. return false;
  300. }
  301. public boolean isEqual(AttributeSet attr) {
  302. return (attr.getAttributeCount() == 0);
  303. }
  304. public AttributeSet copyAttributes() {
  305. return this;
  306. }
  307. public Object getAttribute(Object key) {
  308. return null;
  309. }
  310. public Enumeration getAttributeNames() {
  311. return DefaultMutableTreeNode.EMPTY_ENUMERATION;
  312. }
  313. public boolean containsAttribute(Object name, Object value) {
  314. return false;
  315. }
  316. public boolean containsAttributes(AttributeSet attributes) {
  317. return (attributes.getAttributeCount() == 0);
  318. }
  319. public AttributeSet getResolveParent() {
  320. return null;
  321. }
  322. public boolean equals(Object obj) {
  323. if (this == obj) {
  324. return true;
  325. }
  326. return ((obj instanceof AttributeSet) &&
  327. (((AttributeSet)obj).getAttributeCount() == 0));
  328. }
  329. };
  330. }