001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.html; 014 015import static org.apache.juneau.internal.StringUtils.*; 016 017import java.io.*; 018 019import org.apache.juneau.*; 020import org.apache.juneau.xml.*; 021 022/** 023 * Specialized writer for serializing HTML. 024 */ 025public class HtmlWriter extends XmlWriter { 026 027 /** 028 * Constructor. 029 * 030 * @param out The writer being wrapped. 031 * @param useWhitespace If <jk>true</jk>, tabs will be used in output. 032 * @param maxIndent The maximum indentation level. 033 * @param trimStrings If <jk>true</jk>, strings should be trimmed before they're serialized. 034 * @param quoteChar The quote character to use (i.e. <js>'\''</js> or <js>'"'</js>) 035 * @param uriResolver The URI resolver for resolving URIs to absolute or root-relative form. 036 */ 037 public HtmlWriter(Writer out, boolean useWhitespace, int maxIndent, boolean trimStrings, char quoteChar, 038 UriResolver uriResolver) { 039 super(out, useWhitespace, maxIndent, trimStrings, quoteChar, uriResolver, false, null); 040 } 041 042 /** 043 * Append an attribute with a URI value. 044 * 045 * @param name The attribute name. 046 * @param value The attribute value. Can be any object whose <code>toString()</code> method returns a URI. 047 * @return This object (for method chaining); 048 * @throws IOException If a problem occurred. 049 */ 050 public HtmlWriter attrUri(String name, Object value) throws IOException { 051 super.attrUri((String)null, name, value); 052 return this; 053 } 054 055 056 //-------------------------------------------------------------------------------- 057 // Overridden methods 058 //-------------------------------------------------------------------------------- 059 060 @Override /* XmlSerializerWriter */ 061 public HtmlWriter text(Object o, boolean preserveWhitespace) throws IOException { 062 063 if (o == null) { 064 append("<null/>"); 065 return this; 066 } 067 String s = o.toString(); 068 if (s.isEmpty()) { 069 append("<sp/>"); 070 return this; 071 } 072 073 for (int i = 0; i < s.length(); i++) { 074 char test = s.charAt(i); 075 if (test == '&') 076 append("&"); 077 else if (test == '<') 078 append("<"); 079 else if (test == '>') 080 append(">"); 081 else if (test == '\n') 082 append(preserveWhitespace ? "\n" : "<br/>"); 083 else if (test == '\f') // XML 1.0 doesn't support formfeeds or backslashes, so we have to invent something. 084 append(preserveWhitespace ? "\f" : "<ff/>"); 085 else if (test == '\b') 086 append(preserveWhitespace ? "\b" : "<bs/>"); 087 else if (test == '\t') 088 append(preserveWhitespace ? "\t" : "<sp> </sp>"); 089 else if ((i == 0 || i == s.length()-1) && Character.isWhitespace(test)) { 090 if (preserveWhitespace) 091 append(test); 092 else if (test == ' ') 093 append("<sp> </sp>"); 094 else 095 append("<sp>&#x").append(toHex(test)).append(";</sp>"); 096 } 097 else if (Character.isISOControl(test)) 098 append("&#" + (int) test + ";"); 099 else 100 append(test); 101 } 102 103 return this; 104 } 105 106 @Override /* XmlSerializerWriter */ 107 public HtmlWriter oTag(String ns, String name, boolean needsEncoding) throws IOException { 108 super.oTag(ns, name, needsEncoding); 109 return this; 110 } 111 112 @Override /* XmlSerializerWriter */ 113 public HtmlWriter oTag(String ns, String name) throws IOException { 114 super.oTag(ns, name); 115 return this; 116 } 117 118 @Override /* XmlSerializerWriter */ 119 public HtmlWriter oTag(String name) throws IOException { 120 super.oTag(name); 121 return this; 122 } 123 124 @Override /* XmlSerializerWriter */ 125 public HtmlWriter oTag(int indent, String ns, String name, boolean needsEncoding) throws IOException { 126 super.oTag(indent, ns, name, needsEncoding); 127 return this; 128 } 129 130 @Override /* XmlSerializerWriter */ 131 public HtmlWriter oTag(int indent, String ns, String name) throws IOException { 132 super.oTag(indent, ns, name); 133 return this; 134 } 135 136 @Override /* XmlSerializerWriter */ 137 public HtmlWriter oTag(int indent, String name) throws IOException { 138 super.oTag(indent, name); 139 return this; 140 } 141 142 @Override /* XmlSerializerWriter */ 143 public HtmlWriter tag(String ns, String name, boolean needsEncoding) throws IOException { 144 super.tag(ns, name, needsEncoding); 145 return this; 146 } 147 148 @Override /* XmlSerializerWriter */ 149 public HtmlWriter tag(String ns, String name) throws IOException { 150 super.tag(ns, name); 151 return this; 152 } 153 154 @Override /* XmlSerializerWriter */ 155 public HtmlWriter tag(String name) throws IOException { 156 super.tag(name); 157 return this; 158 } 159 160 @Override /* XmlSerializerWriter */ 161 public HtmlWriter tag(int indent, String name) throws IOException { 162 super.tag(indent, name); 163 return this; 164 } 165 166 @Override /* XmlSerializerWriter */ 167 public HtmlWriter tag(int indent, String ns, String name, boolean needsEncoding) throws IOException { 168 super.tag(indent, ns, name, needsEncoding); 169 return this; 170 } 171 172 @Override /* XmlSerializerWriter */ 173 public HtmlWriter tag(int indent, String ns, String name) throws IOException { 174 super.tag(indent, ns, name); 175 return this; 176 } 177 178 @Override /* XmlSerializerWriter */ 179 public HtmlWriter sTag(String ns, String name) throws IOException { 180 super.sTag(ns, name); 181 return this; 182 } 183 184 @Override /* XmlSerializerWriter */ 185 public HtmlWriter sTag(String ns, String name, boolean needsEncoding) throws IOException { 186 super.sTag(ns, name, needsEncoding); 187 return this; 188 } 189 190 @Override /* XmlSerializerWriter */ 191 public HtmlWriter sTag(int indent, String ns, String name) throws IOException { 192 super.sTag(indent, ns, name); 193 return this; 194 } 195 196 @Override /* XmlSerializerWriter */ 197 public HtmlWriter sTag(int indent, String name) throws IOException { 198 super.sTag(indent, name); 199 return this; 200 } 201 202 @Override /* XmlSerializerWriter */ 203 public HtmlWriter sTag(String name) throws IOException { 204 super.sTag(name); 205 return this; 206 } 207 208 @Override /* XmlSerializerWriter */ 209 public HtmlWriter sTag(int indent, String ns, String name, boolean needsEncoding) throws IOException { 210 super.sTag(indent, ns, name, needsEncoding); 211 return this; 212 } 213 214 @Override /* XmlSerializerWriter */ 215 public HtmlWriter eTag(String ns, String name) throws IOException { 216 super.eTag(ns, name); 217 return this; 218 } 219 220 @Override /* XmlSerializerWriter */ 221 public HtmlWriter eTag(String ns, String name, boolean needsEncoding) throws IOException { 222 super.eTag(ns, name, needsEncoding); 223 return this; 224 } 225 226 @Override /* XmlSerializerWriter */ 227 public HtmlWriter eTag(int indent, String ns, String name) throws IOException { 228 super.eTag(indent, ns, name); 229 return this; 230 } 231 232 @Override /* XmlSerializerWriter */ 233 public HtmlWriter eTag(int indent, String name) throws IOException { 234 super.eTag(indent, name); 235 return this; 236 } 237 238 @Override /* XmlSerializerWriter */ 239 public HtmlWriter eTag(String name) throws IOException { 240 super.eTag(name); 241 return this; 242 } 243 244 @Override /* XmlSerializerWriter */ 245 public HtmlWriter eTag(int indent, String ns, String name, boolean needsEncoding) throws IOException { 246 super.eTag(indent, ns, name, needsEncoding); 247 return this; 248 } 249 250 @Override /* XmlSerializerWriter */ 251 public HtmlWriter attr(String name, Object value) throws IOException { 252 super.attr(name, value); 253 return this; 254 } 255 256 @Override /* XmlSerializerWriter */ 257 public HtmlWriter attr(String ns, String name, Object value) throws IOException { 258 super.attr(ns, name, value); 259 return this; 260 } 261 262 @Override /* XmlSerializerWriter */ 263 public HtmlWriter attr(String ns, String name, Object value, boolean valNeedsEncoding) throws IOException { 264 super.attr(ns, name, value, valNeedsEncoding); 265 return this; 266 } 267 268 @Override /* XmlSerializerWriter */ 269 public HtmlWriter attr(String name, Object value, boolean valNeedsEncoding) throws IOException { 270 super.attr(null, name, value, valNeedsEncoding); 271 return this; 272 } 273 274 @Override /* XmlSerializerWriter */ 275 public HtmlWriter oAttr(String ns, String name) throws IOException { 276 super.oAttr(ns, name); 277 return this; 278 } 279 280 @Override /* SerializerWriter */ 281 public HtmlWriter cr(int depth) throws IOException { 282 if (depth > 0) 283 super.cr(depth); 284 return this; 285 } 286 287 @Override /* SerializerWriter */ 288 public HtmlWriter cre(int depth) throws IOException { 289 if (depth > 0) 290 super.cre(depth); 291 return this; 292 } 293 294 @Override /* SerializerWriter */ 295 public HtmlWriter appendln(int indent, String text) throws IOException { 296 super.appendln(indent, text); 297 return this; 298 } 299 300 @Override /* SerializerWriter */ 301 public HtmlWriter appendln(String text) throws IOException { 302 super.appendln(text); 303 return this; 304 } 305 306 @Override /* SerializerWriter */ 307 public HtmlWriter append(int indent, String text) throws IOException { 308 super.append(indent, text); 309 return this; 310 } 311 312 @Override /* SerializerWriter */ 313 public HtmlWriter append(int indent, char c) throws IOException { 314 super.append(indent, c); 315 return this; 316 } 317 318 @Override /* SerializerWriter */ 319 public HtmlWriter s() throws IOException { 320 super.s(); 321 return this; 322 } 323 324 @Override /* SerializerWriter */ 325 public HtmlWriter q() throws IOException { 326 super.q(); 327 return this; 328 } 329 330 @Override /* SerializerWriter */ 331 public HtmlWriter i(int indent) throws IOException { 332 super.i(indent); 333 return this; 334 } 335 336 @Override /* SerializerWriter */ 337 public HtmlWriter nl(int indent) throws IOException { 338 super.nl(indent); 339 return this; 340 } 341 342 @Override /* SerializerWriter */ 343 public HtmlWriter append(Object text) throws IOException { 344 super.append(text); 345 return this; 346 } 347 348 @Override /* SerializerWriter */ 349 public HtmlWriter append(String text) throws IOException { 350 super.append(text); 351 return this; 352 } 353 354 @Override /* SerializerWriter */ 355 public HtmlWriter append(char c) throws IOException { 356 super.append(c); 357 return this; 358 } 359}