001 package de.java2html.converter;
002 
003 import java.io.BufferedWriter;
004 import java.io.IOException;
005 import java.text.MessageFormat;
006 
007 import de.java2html.Version;
008 import de.java2html.javasource.TypedSource;
009 import de.java2html.javasource.TypedSourceIterator;
010 import de.java2html.javasource.SourceRun;
011 import de.java2html.javasource.SourceType;
012 import de.java2html.options.HorizontalAlignment;
013 import de.java2html.options.IHorizontalAlignmentVisitor;
014 import de.java2html.options.JavaSourceConversionOptions;
015 import de.java2html.options.JavaSourceStyleEntry;
016 import de.java2html.options.JavaSourceStyleTable;
017 import de.java2html.util.HtmlUtilities;
018 import de.java2html.util.StringHolder;
019 
020 /**
021  * Algorithm and stuff for converting a
022  {@link de.java2html.javasource.TypedSource} object to to a HTML string
023  * representation.
024  
025  * The result is XHTML1.0 Transitional compliant.
026  
027  * For questions, suggestions, bug-reports, enhancement-requests etc. I may be
028  * contacted at: <a href="mailto:markus@jave.de">markus@jave.de</a>
029  
030  * The Java2html home page is located at: <a href="http://www.java2html.de">
031  * http://www.java2html.de</a>
032  
033  @author <a href="mailto:markus@jave.de">Markus Gebhard</a>
034  
035  * Copyright (C) Markus Gebhard 2000-2002
036  
037  * This program is free software; you can redistribute it and/or modify it
038  * under the terms of the GNU General Public License as published by the Free
039  * Software Foundation; either version 2 of the License, or (at your option)
040  * any later version.
041  
042  * This program is distributed in the hope that it will be useful, but WITHOUT
043  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
044  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
045  * more details.
046  
047  * You should have received a copy of the GNU General Public License along with
048  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
049  * Place - Suite 330, Boston, MA 02111-1307, USA.
050  */
051 public class JavaSource2HTMLConverter extends AbstractJavaSourceConverter {
052   /**
053    * Flag indication whether html output contains a link to the
054    * Java2Html-Homepage or not.
055    
056    @deprecated As of Jan 2, 2004 (Markus Gebhard) replaced by
057    *             {@link de.java2html.options.JavaSourceConversionOptions#setShowJava2HtmlLink(boolean)}
058    */
059   @Deprecated
060   public static boolean java2HtmlHomepageLinkEnabled = false;
061 
062   /**
063    * Site header for a html page. Is not used by this class, but can be used
064    * from outside to add it to one or more converted
065    */
066   private final static String HTML_SITE_HEADER = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
067       //     "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"
068       // \"http://www.w3.org/TR/html4/loose.dtd\">\n"
069       "<html><head>\n"
070       "<title>{0}</title>\n"
071       "  <style type=\"text/css\">\n"
072       "    <!--code '{' font-family: Courier New, Courier; font-size: 10pt; margin: 0px; '}'-->\n"
073       "  </style>\n"
074       "  <meta http-equiv=\"Content-Type\" content=\"text/html; charset={1}\" />\n"
075       "</head><body>\n";
076 
077   /**
078    * Site footer for a html page. Is not used by this class, but can be used
079    * from outside to add it to one or more converted
080    */
081   private final static String HTML_SITE_FOOTER = "\n</body></html>";
082 
083   /** Block seperator for between two blocks of converted source code */
084   private final static String HTML_BLOCK_SEPARATOR = "<p />\n";
085 
086   /** HTML-Header for a block (!) of converted code */
087   private final static String HTML_BLOCK_HEADER = "\n\n"
088       "<!-- ======================================================== -->\n"
089       "<!-- = Java Sourcecode to HTML automatically converted code = -->\n"
090       "<!-- =   "
091       + Version.getJava2HtmlConverterTitle()
092       " "
093       + Version.getBuildDate()
094       " by Markus Gebhard  markus@jave.de   = -->\n"
095       "<!-- =     Further information: http://www.java2html.de     = -->\n"
096       "<div align=\"{0}\" class=\"java\">\n"
097       "<table border=\"{1}\" cellpadding=\"3\" "
098       "cellspacing=\"0\" bgcolor=\"{2}\">\n";
099 
100   /** HTML-code for before the headline */
101   private final static String HTML_HEAD_START = "  <!-- start headline -->\n"
102       "   <tr>\n"
103       "    <td colspan=\"2\">\n"
104       "     <center><font size=\"+2\">\n"
105       "      <code><b>\n";
106 
107   /** HTML-code for after the headline */
108   private final static String HTML_HEAD_END = "      </b></code>\n"
109       "     </font></center>\n"
110       "    </td>\n"
111       "   </tr>\n"
112       "  <!-- end headline -->\n";
113 
114   /**
115    * HTML-code for before the second column (contaning the converted source
116    * code)
117    */
118   private final static String HTML_COL2_START = "  <!-- start source code -->\n"
119       "   <td nowrap=\"nowrap\" valign=\"top\" align=\"left\">\n"
120       "    <code>\n";
121 
122   /**
123    * HTML-code for after the second column (contaning the converted source
124    * code)
125    */
126   private final static String HTML_COL2_END = "</code>\n"
127       "    \n"
128       "   </td>\n"
129       "  <!-- end source code -->\n";
130 
131   /**
132    * HTML-code for the bottom line (containing a little link to the
133    * java2html-homepage). Can be disabled by setting
134    {@link #java2HtmlHomepageLinkEnabled}
135    */
136   private final static String HTML_LINK = "  <!-- start Java2Html link -->\n"
137       "   <tr>\n"
138       "    <td align=\"right\">\n"
139       "<small>\n"
140       "<a href=\"http://www.java2html.de\" target=\"_blank\">Java2html</a>\n"
141       "</small>\n"
142       "    </td>\n"
143       "   </tr>\n"
144       "  <!-- end Java2Html link -->\n";
145 
146   /** HTML-code for after the end of the block */
147   private final static String HTML_BLOCK_FOOTER =
148   //"\n"+ sieht schoener aus, wenn kein Zeilenumbruch mehr!
149   "</table>\n"
150       "</div>\n"
151       "<!-- =       END of automatically generated HTML code       = -->\n"
152       "<!-- ======================================================== -->\n\n";
153 
154   /**
155    * The html representation of the colors used for different source
156    */
157 
158   private int lineCifferCount;
159 
160   public JavaSource2HTMLConverter() {
161     super(new ConverterMetaData("html""XHTML 1.0 Transitional (inlined fonts)""html"));
162   }
163 
164   @Override
165   public String getDocumentHeader(JavaSourceConversionOptions options, String title) {
166     if (title == null) {
167       title = ""//$NON-NLS-1$
168     }
169     
170     return MessageFormat.format(HTML_SITE_HEADER, new Object[]{ title, options.getCharset() });
171   }
172 
173   @Override
174   public String getDocumentFooter(JavaSourceConversionOptions options) {
175     return HTML_SITE_FOOTER;
176   }
177 
178   @Override
179   public String getBlockSeparator(JavaSourceConversionOptions options) {
180     return HTML_BLOCK_SEPARATOR;
181   }
182 
183   @Override
184   public void convert(TypedSource source, JavaSourceConversionOptions options, BufferedWriter writer)
185       throws IOException {
186     if (source == null) {
187       throw new IllegalStateException("Trying to write out converted code without having source set.");
188     }
189 
190     //Header
191     final String alignValue = getHtmlAlignValue(options.getHorizontalAlignment());
192     final String bgcolorValue = options.getStyleTable().get(SourceType.BACKGROUND).getHtmlColor();
193     final String borderValue = options.isShowTableBorder() "2" "0";
194 
195     writer.write(MessageFormat.format(HTML_BLOCK_HEADER, new Object[]{ alignValue, borderValue, bgcolorValue }));
196 
197     if (options.isShowFileName() && source.getFileName() != null) {
198       writeFileName(source, writer);
199     }
200 
201     writer.write("   <tr>");
202     writer.write("\n");
203 
204     writeSourceCode(source, options, writer);
205 
206     writer.write("   </tr>");
207     writer.write("\n");
208 
209     //5) Footer with link to web site
210     if (options.isShowJava2HtmlLink() || java2HtmlHomepageLinkEnabled) {
211       writer.write(HTML_LINK);
212     }
213     writer.write(HTML_BLOCK_FOOTER);
214   }
215 
216   private String getHtmlAlignValue(HorizontalAlignment alignment) {
217     final StringHolder stringHolder = new StringHolder();
218     alignment.accept(new IHorizontalAlignmentVisitor() {
219       public void visitLeftAlignment(HorizontalAlignment horizontalAlignment) {
220         stringHolder.setValue("left");
221       }
222 
223       public void visitRightAlignment(HorizontalAlignment horizontalAlignment) {
224         stringHolder.setValue("right");
225       }
226 
227       public void visitCenterAlignment(HorizontalAlignment horizontalAlignment) {
228         stringHolder.setValue("center");
229       }
230     });
231     return stringHolder.getValue();
232   }
233 
234   private void writeFileName(TypedSource source, BufferedWriter writerthrows IOException {
235     writer.write(HTML_HEAD_START);
236     writer.write(source.getFileName());
237     writer.write("\n");
238     writer.write(HTML_HEAD_END);
239   }
240 
241   private void writeSourceCode(TypedSource source, JavaSourceConversionOptions options, BufferedWriter writer)
242       throws IOException {
243     writer.write(HTML_COL2_START);
244 
245     lineCifferCount = String.valueOf(source.getLineCount()).length();
246 
247     final TypedSourceIterator iterator = source.getIterator();
248     int lineNumber = 1;
249     while (iterator.hasNext()) {
250       final SourceRun run = iterator.getNext();
251 
252       if (run.isAtStartOfLine()) {
253         if (options.isAddLineAnchors()) {
254           writeLineAnchorStart(options, writer, lineNumber);
255         }
256         if (options.isShowLineNumbers()) {
257           writeLineNumber(options, writer, lineNumber);
258         }
259         if (options.isAddLineAnchors()) {
260           writeLineAnchorEnd(writer);
261         }
262         lineNumber++;
263       }
264 
265       toHTML(options.getStyleTable(), run, writer);
266       if (run.isAtEndOfLine() && iterator.hasNext()) {
267         writer.write("<br />");
268         writer.write("\n");
269       }
270     }
271     writer.write(HTML_COL2_END);
272   }
273 
274   private void writeLineAnchorEnd(BufferedWriter writerthrows IOException {
275     writer.write("</a>");
276   }
277 
278   private void writeLineAnchorStart(JavaSourceConversionOptions options, BufferedWriter writer, int lineNumber)
279       throws IOException {
280     writer.write("<a name=\"");
281     writer.write(options.getLineAnchorPrefix() + lineNumber);
282     writer.write("\">");
283   }
284 
285   private void writeLineNumber(JavaSourceConversionOptions options, BufferedWriter writer, int lineNo)
286       throws IOException {
287     final JavaSourceStyleEntry styleEntry = options.getStyleTable().get(SourceType.LINE_NUMBERS);
288     writeStyleStart(writer, styleEntry);
289 
290     final String lineNumber = String.valueOf(lineNo);
291     int cifferCount = lineCifferCount - lineNumber.length();
292     while (cifferCount > 0) {
293       writer.write('0');
294       --cifferCount;
295     }
296 
297     writer.write(lineNumber);
298     writeStyleEnd(writer, styleEntry);
299     writer.write("&nbsp;");
300   }
301 
302   private void toHTML(JavaSourceStyleTable styleTable, SourceRun run, BufferedWriter writer)
303       throws IOException {
304     //  result.append(htmlColors[sourceTypes[start]]);
305     final JavaSourceStyleEntry style = styleTable.get(run.getType());
306 
307     writeStyleStart(writer, style);
308 
309     final String t = HtmlUtilities.encode(run.getCode()"\n ");
310 
311     for (int i = 0; i < t.length(); ++i) {
312       final char ch = t.charAt(i);
313       if (ch == ' ') {
314         writer.write("&nbsp;");
315       }
316       else {
317         writer.write(ch);
318       }
319     }
320 
321     writeStyleEnd(writer, style);
322   }
323 
324   private void writeStyleStart(BufferedWriter writer, JavaSourceStyleEntry stylethrows IOException {
325     writer.write("<font color=\"" + style.getHtmlColor() "\">");
326     if (style.isBold()) {
327       writer.write("<b>");
328     }
329     if (style.isItalic()) {
330       writer.write("<i>");
331     }
332   }
333 
334   private void writeStyleEnd(BufferedWriter writer, JavaSourceStyleEntry stylethrows IOException {
335     if (style.isItalic()) {
336       writer.write("</i>");
337     }
338     if (style.isBold()) {
339       writer.write("</b>");
340     }
341     writer.write("</font>");
342   }
343 }