001 package edu.nrao.sss.html; 002 003 import javax.swing.text.html.HTML; 004 005 /** 006 * An attribute (see {@link javax.swing.text.html.HTML.Attribute}) 007 * of an HTML element. 008 * <p> 009 * <b>Version Info:</b> 010 * <table style="margin-left:2em"> 011 * <tr><td>$Revision: 545 $</td></tr> 012 * <tr><td>$Date: 2007-04-19 10:38:45 -0600 (Thu, 19 Apr 2007) $</td></tr> 013 * <tr><td>$Author: dharland $</td></tr> 014 * </table></p> 015 * 016 * @author David M. Harland 017 * @since 2007-03-15 018 */ 019 public class HtmlAttribute 020 { 021 private HTML.Attribute type; //Not mutable after construction 022 private String value; 023 024 /** 025 * Creates a new HTML attribute of the given type and value. 026 * 027 * @param attrName the name, or type, of this attribute. 028 * This value must be a valid attribute name. 029 * Validity is determined by 030 * {@link HTML#getAttributeKey(String)}. 031 * A list of known attribute names may be found in 032 * {@link javax.swing.text.html.HTML.Attribute}.</p> 033 * 034 * @param attrValue the value of this attribute. 035 * See {@link #setValue(String)} for the rules about this 036 * parameter. 037 */ 038 public HtmlAttribute(String attrName, String attrValue) 039 { 040 //Use name to get a valid attribute 041 type = HTML.getAttributeKey(attrName); 042 043 if (type == null) 044 throw new IllegalArgumentException("Attribute name [" + attrName + 045 "] is not recognized as a valid name."); 046 setValue(attrValue); 047 } 048 049 /** 050 * Creates a new HTML attribute of the given type and value. 051 * 052 * @param attrType the type of this attribute. If this parameter is 053 * <i>null</i> an {@code IllegalArgumentException} 054 * will be thrown. 055 * 056 * @param attrValue the value of this attribute. 057 * See {@link #setValue(String)} for the rules about this 058 * parameter. 059 */ 060 public HtmlAttribute(HTML.Attribute attrType, String attrValue) 061 { 062 if (attrType == null) 063 throw new IllegalArgumentException("May not have null attribute type."); 064 065 type = attrType; 066 setValue(attrValue); 067 } 068 069 /** 070 * Creates a new HTML attribute of the given type and with a value of 071 * the empty string (<tt>""</tt>). 072 * 073 * @param attrType the type of this attribute. If this parameter is 074 * <i>null</i> an {@code IllegalArgumentException} 075 * will be thrown. 076 */ 077 public HtmlAttribute(HTML.Attribute attrType) 078 { 079 this(attrType, ""); 080 } 081 082 /** 083 * Returns the type of this attribute. 084 * @return the type of this attribute. This value is guaranteeed to be 085 * non-null. 086 */ 087 public HTML.Attribute getType() 088 { 089 return type; 090 } 091 092 /** 093 * Sets the value of this attribute. 094 * 095 * @param newValue a new value for this attribute. If this parameter is 096 * <i>null</i>, it will be replaced by the empty 097 * string (<tt>""</tt>). This parameter may contain 098 * single quote (<tt>'</tt>) or double quote 099 * (<tt>"</tt>) characters, but not both. If it does, 100 * an {@code IllegalArgumentException} will be thrown 101 * and this attribute's value will be left in its 102 * present state. 103 */ 104 public final void setValue(String newValue) 105 { 106 if (newValue == null) 107 newValue = ""; 108 109 if (newValue.contains("'") && newValue.contains("\"")) 110 throw new IllegalArgumentException( 111 "newValue [" + newValue + 112 "] may not have both single and double quotes."); 113 114 value = newValue; 115 } 116 117 /** 118 * Returns the value of this attribute. 119 * 120 * @return the value of this attribute. This value is guaranteeed to be 121 * non-null, but could be an empty string (<tt>""</tt>). 122 */ 123 public String getValue() 124 { 125 return value; 126 } 127 128 /** 129 * Creates and returns a new HTML attribute by parsing {@code nameValueText}. 130 * 131 * @param nameValueText the HTML form of this attribute. 132 * The expected form of the text is: 133 * <pre> name="value"</pre> 134 * Values may be quoted with either single (') or double (") quotes. 135 * Leading and trailing whitespace is permitted and will be trimmed during 136 * parsing. 137 * The <tt>name</tt> must be a valid attribute name. Validity is determined 138 * by {@link HTML#getAttributeKey(String)}. A list of known attribute names 139 * may be found in {@link javax.swing.text.html.HTML.Attribute}.</p> 140 * 141 * @return a new HTML attribute by parsing {@code nameValueText}. 142 * 143 * @throws IllegalArgumentException if anything goes wrong during parsing. 144 */ 145 public static HtmlAttribute parse(String nameValueText) 146 { 147 StringBuilder nameValueBuff = new StringBuilder(nameValueText.trim()); 148 StringBuilder tempBuff = new StringBuilder(); 149 int charCount = nameValueBuff.length(); 150 151 String name, value; 152 153 //Ensure we have format name="value" 154 try 155 { 156 //Look for the name 157 int c = 0; 158 char ch = nameValueBuff.charAt(c); 159 while (ch != '=') 160 { 161 tempBuff.append(ch); 162 ch = nameValueBuff.charAt(++c); 163 } 164 165 name = tempBuff.toString().trim().toLowerCase(); 166 167 //Skip any white space after '=' 168 c++; 169 while (Character.isWhitespace(nameValueBuff.charAt(c))) 170 c++; 171 172 //Look for the value 173 tempBuff.delete(0, tempBuff.length()); 174 char quoteChar = nameValueBuff.charAt(c); //Could be " or ' 175 ch = nameValueBuff.charAt(++c); 176 while (ch != quoteChar) 177 { 178 tempBuff.append(ch); 179 ch = nameValueBuff.charAt(++c); 180 } 181 182 if (++c < charCount) 183 throw new IllegalArgumentException( 184 "Extra characters found beyond value's closing quote."); 185 186 value = tempBuff.toString(); 187 } 188 catch (Exception ex) 189 { 190 throw new IllegalArgumentException("Could not parse nameValueText [" + 191 nameValueText + "]: " + 192 ex.getMessage()); 193 } 194 195 //Use name to get a valid attribute 196 HTML.Attribute attrType = HTML.getAttributeKey(name); 197 198 if (attrType == null) 199 throw new IllegalArgumentException("Attribute name [" + name + 200 "] in nameValueText [" + nameValueText+ 201 "] is not recognized as a valid name."); 202 203 return new HtmlAttribute(attrType, value); 204 } 205 206 /** 207 * Returns a string of the form <tt>name="value"</tt>. 208 * If <i>value</i> itself contains double-quote characters, 209 * the returned string will be of the form <tt>name='value'</tt>. 210 */ 211 @Override 212 public String toString() 213 { 214 char quoteChar = value.contains("\"") ? '\'' : '"'; 215 216 StringBuilder buff = new StringBuilder(type.toString()); 217 218 buff.append('=').append(quoteChar).append(value).append(quoteChar); 219 220 return buff.toString(); 221 } 222 223 /** Returns <i>true</i> if {@code o} is equal to this attribute. */ 224 @Override 225 public boolean equals(Object o) 226 { 227 //Quick exit if o is this 228 if (o == this) 229 return true; 230 231 //Quick exit if o is null 232 if (o == null) 233 return false; 234 235 //Quick exit if classes are different 236 if (!o.getClass().equals(this.getClass())) 237 return false; 238 239 HtmlAttribute other = (HtmlAttribute)o; 240 241 return this.type.equals(other.type) && 242 this.value.equals(other.value); 243 } 244 245 @Override 246 /** Returns a hash code value for this cell. */ 247 public int hashCode() 248 { 249 //Taken from the Effective Java book by Joshua Bloch. 250 //The constants 17 & 37 are arbitrary & carry no meaning. 251 int result = 17; 252 253 //You MUST keep this method in synch w/ equals 254 255 result = 37 * result + type.hashCode(); 256 result = 37 * result + value.hashCode(); 257 258 return result; 259 } 260 /* 261 public static void main(String[] args) 262 { 263 HtmlAttribute attr = HtmlAttribute.parse(" name ='Richard \"Dick\" Cheney' "); 264 System.out.println(attr); 265 266 attr = HtmlAttribute.parse(attr.toString()); 267 System.out.println(attr); 268 269 attr = HtmlAttribute.parse("name='Barney' class=\"72\" color='pale'"); 270 System.out.println(attr); 271 272 //attr = HtmlAttribute.parse("name='Fred Flintstone\""); 273 //System.out.println(attr); 274 275 //attr = HtmlAttribute.parse("fruit=\"Apple\""); 276 //System.out.println(attr); 277 } 278 */ 279 }