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   //-----------------------------------------------------------------------------------------------------------------
044   // Overridden methods
045   //-----------------------------------------------------------------------------------------------------------------
046
047   @Override /* XmlSerializerWriter */
048   public HtmlWriter text(Object o, boolean preserveWhitespace) throws IOException {
049
050      if (o == null) {
051         append("<null/>");
052         return this;
053      }
054      String s = o.toString();
055      if (s.isEmpty()) {
056         append("<sp/>");
057         return this;
058      }
059
060      for (int i = 0; i < s.length(); i++) {
061         char test = s.charAt(i);
062         if (test == '&')
063            append("&amp;");
064         else if (test == '<')
065            append("&lt;");
066         else if (test == '>')
067            append("&gt;");
068         else if (test == '\n')
069            append(preserveWhitespace ? "\n" : "<br/>");
070         else if (test == '\f')  // XML 1.0 doesn't support formfeeds or backslashes, so we have to invent something.
071            append(preserveWhitespace ? "\f" : "<ff/>");
072         else if (test == '\b')
073            append(preserveWhitespace ? "\b" : "<bs/>");
074         else if (test == '\t')
075            append(preserveWhitespace ? "\t" : "<sp>&#x2003;</sp>");
076         else if ((i == 0 || i == s.length()-1) && Character.isWhitespace(test)) {
077            if (preserveWhitespace)
078               append(test);
079            else if (test == ' ')
080               append("<sp> </sp>");
081            else
082               append("<sp>&#x").append(toHex4(test)).append(";</sp>");
083         }
084         else if (Character.isISOControl(test))
085            append("&#" + (int) test + ";");
086         else
087            append(test);
088      }
089
090      return this;
091   }
092
093   @Override /* XmlSerializerWriter */
094   public HtmlWriter oTag(String ns, String name, boolean needsEncoding) throws IOException {
095      super.oTag(ns, name, needsEncoding);
096      return this;
097   }
098
099   @Override /* XmlSerializerWriter */
100   public HtmlWriter oTag(String ns, String name) throws IOException {
101      super.oTag(ns, name);
102      return this;
103   }
104
105   @Override /* XmlSerializerWriter */
106   public HtmlWriter oTag(String name) throws IOException {
107      super.oTag(name);
108      return this;
109   }
110
111   @Override /* XmlSerializerWriter */
112   public HtmlWriter oTag(int indent, String ns, String name, boolean needsEncoding) throws IOException {
113      super.oTag(indent, ns, name, needsEncoding);
114      return this;
115   }
116
117   @Override /* XmlSerializerWriter */
118   public HtmlWriter oTag(int indent, String ns, String name) throws IOException {
119      super.oTag(indent, ns, name);
120      return this;
121   }
122
123   @Override /* XmlSerializerWriter */
124   public HtmlWriter oTag(int indent, String name) throws IOException {
125      super.oTag(indent, name);
126      return this;
127   }
128
129   @Override /* XmlSerializerWriter */
130   public HtmlWriter tag(String ns, String name, boolean needsEncoding) throws IOException {
131      super.tag(ns, name, needsEncoding);
132      return this;
133   }
134
135   @Override /* XmlSerializerWriter */
136   public HtmlWriter tag(String ns, String name) throws IOException {
137      super.tag(ns, name);
138      return this;
139   }
140
141   @Override /* XmlSerializerWriter */
142   public HtmlWriter tag(String name) throws IOException {
143      super.tag(name);
144      return this;
145   }
146
147   @Override /* XmlSerializerWriter */
148   public HtmlWriter tag(int indent, String name) throws IOException {
149      super.tag(indent, name);
150      return this;
151   }
152
153   @Override /* XmlSerializerWriter */
154   public HtmlWriter tag(int indent, String ns, String name, boolean needsEncoding) throws IOException {
155      super.tag(indent, ns, name, needsEncoding);
156      return this;
157   }
158
159   @Override /* XmlSerializerWriter */
160   public HtmlWriter tag(int indent, String ns, String name) throws IOException {
161      super.tag(indent, ns, name);
162      return this;
163   }
164
165   @Override /* XmlSerializerWriter */
166   public HtmlWriter sTag(String ns, String name) throws IOException {
167      super.sTag(ns, name);
168      return this;
169   }
170
171   @Override /* XmlSerializerWriter */
172   public HtmlWriter sTag(String ns, String name, boolean needsEncoding) throws IOException {
173      super.sTag(ns, name, needsEncoding);
174      return this;
175   }
176
177   @Override /* XmlSerializerWriter */
178   public HtmlWriter sTag(int indent, String ns, String name) throws IOException {
179      super.sTag(indent, ns, name);
180      return this;
181   }
182
183   @Override /* XmlSerializerWriter */
184   public HtmlWriter sTag(int indent, String name) throws IOException {
185      super.sTag(indent, name);
186      return this;
187   }
188
189   @Override /* XmlSerializerWriter */
190   public HtmlWriter sTag(String name) throws IOException {
191      super.sTag(name);
192      return this;
193   }
194
195   @Override /* XmlSerializerWriter */
196   public HtmlWriter sTag(int indent, String ns, String name, boolean needsEncoding) throws IOException {
197      super.sTag(indent, ns, name, needsEncoding);
198      return this;
199   }
200
201   @Override /* XmlSerializerWriter */
202   public HtmlWriter eTag(String ns, String name) throws IOException {
203      super.eTag(ns, name);
204      return this;
205   }
206
207   @Override /* XmlSerializerWriter */
208   public HtmlWriter eTag(String ns, String name, boolean needsEncoding) throws IOException {
209      super.eTag(ns, name, needsEncoding);
210      return this;
211   }
212
213   @Override /* XmlSerializerWriter */
214   public HtmlWriter eTag(int indent, String ns, String name) throws IOException {
215      super.eTag(indent, ns, name);
216      return this;
217   }
218
219   @Override /* XmlSerializerWriter */
220   public HtmlWriter eTag(int indent, String name) throws IOException {
221      super.eTag(indent, name);
222      return this;
223   }
224
225   @Override /* XmlSerializerWriter */
226   public HtmlWriter eTag(String name) throws IOException {
227      super.eTag(name);
228      return this;
229   }
230
231   @Override /* XmlSerializerWriter */
232   public HtmlWriter eTag(int indent, String ns, String name, boolean needsEncoding) throws IOException {
233      super.eTag(indent, ns, name, needsEncoding);
234      return this;
235   }
236
237   @Override /* XmlSerializerWriter */
238   public HtmlWriter attr(String name, Object value) throws IOException {
239      super.attr(name, value);
240      return this;
241   }
242
243   @Override /* XmlSerializerWriter */
244   public HtmlWriter attr(String ns, String name, Object value) throws IOException {
245      super.attr(ns, name, value);
246      return this;
247   }
248
249   @Override /* XmlSerializerWriter */
250   public HtmlWriter attr(String ns, String name, Object value, boolean valNeedsEncoding) throws IOException {
251      super.attr(ns, name, value, valNeedsEncoding);
252      return this;
253   }
254
255   @Override /* XmlSerializerWriter */
256   public HtmlWriter attr(String name, Object value, boolean valNeedsEncoding) throws IOException {
257      super.attr(null, name, value, valNeedsEncoding);
258      return this;
259   }
260
261   @Override /* XmlSerializerWriter */
262   public HtmlWriter oAttr(String ns, String name) throws IOException {
263      super.oAttr(ns, name);
264      return this;
265   }
266
267   @Override /* SerializerWriter */
268   public HtmlWriter cr(int depth) throws IOException {
269      if (depth > 0)
270         super.cr(depth);
271      return this;
272   }
273
274   @Override /* SerializerWriter */
275   public HtmlWriter cre(int depth) throws IOException {
276      if (depth > 0)
277         super.cre(depth);
278      return this;
279   }
280
281   @Override /* SerializerWriter */
282   public HtmlWriter appendln(int indent, String text) throws IOException {
283      super.appendln(indent, text);
284      return this;
285   }
286
287   @Override /* SerializerWriter */
288   public HtmlWriter appendln(String text) throws IOException {
289      super.appendln(text);
290      return this;
291   }
292
293   @Override /* SerializerWriter */
294   public HtmlWriter append(int indent, String text) throws IOException {
295      super.append(indent, text);
296      return this;
297   }
298
299   @Override /* SerializerWriter */
300   public HtmlWriter append(int indent, char c) throws IOException {
301      super.append(indent, c);
302      return this;
303   }
304
305   @Override /* SerializerWriter */
306   public HtmlWriter s() throws IOException {
307      super.s();
308      return this;
309   }
310
311   @Override /* SerializerWriter */
312   public HtmlWriter q() throws IOException {
313      super.q();
314      return this;
315   }
316
317   @Override /* SerializerWriter */
318   public HtmlWriter i(int indent) throws IOException {
319      super.i(indent);
320      return this;
321   }
322
323   @Override /* SerializerWriter */
324   public HtmlWriter nl(int indent) throws IOException {
325      super.nl(indent);
326      return this;
327   }
328
329   @Override /* SerializerWriter */
330   public HtmlWriter append(Object text) throws IOException {
331      super.append(text);
332      return this;
333   }
334
335   @Override /* SerializerWriter */
336   public HtmlWriter append(String text) throws IOException {
337      super.append(text);
338      return this;
339   }
340
341   @Override /* SerializerWriter */
342   public HtmlWriter append(char c) throws IOException {
343      super.append(c);
344      return this;
345   }
346}