001 /*--------------------------------------------------------------------------+ 002 $Id: HTMLWriter.java 28096 2010-06-09 13:12:48Z hummelb $ 003 | | 004 | Copyright 2005-2010 Technische Universitaet Muenchen | 005 | | 006 | Licensed under the Apache License, Version 2.0 (the "License"); | 007 | you may not use this file except in compliance with the License. | 008 | You may obtain a copy of the License at | 009 | | 010 | http://www.apache.org/licenses/LICENSE-2.0 | 011 | | 012 | Unless required by applicable law or agreed to in writing, software | 013 | distributed under the License is distributed on an "AS IS" BASIS, | 014 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 015 | See the License for the specific language governing permissions and | 016 | limitations under the License. | 017 +--------------------------------------------------------------------------*/ 018 package edu.tum.cs.commons.html; 019 020 import java.io.File; 021 import java.io.IOException; 022 import java.io.OutputStream; 023 import java.io.OutputStreamWriter; 024 import java.io.PrintStream; 025 import java.io.PrintWriter; 026 import java.io.UnsupportedEncodingException; 027 028 import edu.tum.cs.commons.filesystem.FileSystemUtils; 029 import edu.tum.cs.commons.string.StringUtils; 030 import edu.tum.cs.commons.xml.IXMLResolver; 031 import edu.tum.cs.commons.xml.XMLWriter; 032 033 /** 034 * This class is used for writing HTML. 035 * 036 * @author Benjamin Hummel 037 * @author $Author: hummelb $ 038 * @version $Rev: 28096 $ 039 * @levd.rating GREEN Hash: 8D23F1A3EAAA692885E5A25667EF254D 040 */ 041 public class HTMLWriter extends XMLWriter<EHTMLElement, EHTMLAttribute> { 042 043 /** The CSS manager class used. */ 044 private final CSSManagerBase cssManager; 045 046 /** 047 * Creates a new writer for HTML documents. 048 * 049 * @param file 050 * the file to write to. 051 */ 052 public HTMLWriter(File file, CSSManagerBase cssManager) throws IOException { 053 this(new PrintStream(file, FileSystemUtils.UTF8_ENCODING), cssManager); 054 } 055 056 /** 057 * Creates a new writer for HTML documents. 058 * 059 * @param stream 060 * the stream to print to. 061 */ 062 public HTMLWriter(OutputStream stream, CSSManagerBase cssManager) { 063 super(new PrintWriter(wrapStream(stream)), new HTMLResolver()); 064 this.cssManager = cssManager; 065 } 066 067 /** 068 * Helper method for {@link #HTMLWriter(OutputStream, CSSManagerBase)} to 069 * deal with the exception. 070 */ 071 private static OutputStreamWriter wrapStream(OutputStream stream) { 072 try { 073 return new OutputStreamWriter(stream, FileSystemUtils.UTF8_ENCODING); 074 } catch (UnsupportedEncodingException e) { 075 throw new AssertionError("UTF-8 should be supported!"); 076 } 077 } 078 079 /** 080 * Creates a new writer for HTML documents. 081 * 082 * @param writer 083 * the writer to print to. 084 */ 085 public HTMLWriter(PrintWriter writer, CSSManagerBase cssManager) { 086 super(writer, new HTMLResolver()); 087 this.cssManager = cssManager; 088 } 089 090 /** 091 * This adds a default header for HTML files consisting of the XML header 092 * and a DOCTYPE of the xhtml frameset DTD. 093 * <p> 094 * XML version is set to "1.0", encoding provided by a parameter, and doc 095 * type definition to XHTML 1.0 Frameset. 096 */ 097 public void addStdHeader(String encoding) { 098 addHeader("1.0", encoding); 099 addPublicDocTypeDefintion(EHTMLElement.HTML, 100 "-//W3C//DTD XHTML 1.0 Frameset//EN", 101 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"); 102 } 103 104 /** 105 * This adds a default header for HTML files consisting of the XML header 106 * and a DOCTYPE of the xhtml frameset DTD. 107 * <p> 108 * XML version is set to "1.0", encoding to "UTF-8", and doc type definition 109 * to XHTML 1.0 Frameset. 110 */ 111 public void addStdHeader() { 112 addStdHeader(FileSystemUtils.UTF8_ENCODING); 113 } 114 115 /** 116 * {@inheritDoc} 117 * 118 * Made this public here. 119 */ 120 @Override 121 public void addRawString(String html) { 122 super.addRawString(html); 123 } 124 125 /** 126 * Adds a line separator with closing and open tag (see 127 * {@link #addNewLine()}. 128 */ 129 public void addRawNewLine() { 130 addRawString(StringUtils.CR); 131 } 132 133 /** 134 * Adds an attribute to the currently open element but checks in addition if 135 * the attribute may be added at all. 136 * 137 * @throws HTMLWriterException 138 * if the attribute is not allowed for the current element. 139 */ 140 @Override 141 public void addAttribute(EHTMLAttribute attribute, Object value) { 142 if (!getCurrentElement().allowsAttribute(attribute)) { 143 throw new HTMLWriterException("Attribute " + attribute 144 + " not allowed for element " + getCurrentElement()); 145 } 146 147 if (attribute == EHTMLAttribute.STYLE 148 || attribute == EHTMLAttribute.CLASS) { 149 if (!(value instanceof CSSDeclarationBlock)) { 150 throw new HTMLWriterException( 151 "The argument for STYLE and CLASS attributes must be a " 152 + CSSDeclarationBlock.class.getSimpleName() 153 + "!"); 154 } 155 } 156 157 if (attribute == EHTMLAttribute.STYLE) { 158 super.addAttribute(attribute, ((CSSDeclarationBlock) value) 159 .toInlineStyle()); 160 } else if (attribute == EHTMLAttribute.CLASS) { 161 super.addAttribute(attribute, cssManager 162 .getCSSClassName((CSSDeclarationBlock) value)); 163 } else { 164 super.addAttribute(attribute, value); 165 } 166 } 167 168 /** The resolver used for the {@link HTMLWriter}. */ 169 public static class HTMLResolver implements 170 IXMLResolver<EHTMLElement, EHTMLAttribute> { 171 172 /** {@inheritDoc} */ 173 public String resolveAttributeName(EHTMLAttribute attribute) { 174 return attribute.toString(); 175 } 176 177 /** {@inheritDoc} */ 178 public String resolveElementName(EHTMLElement element) { 179 return element.toString(); 180 } 181 182 /** {@inheritDoc} */ 183 public Class<EHTMLAttribute> getAttributeClass() { 184 return EHTMLAttribute.class; 185 } 186 } 187 }