001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. 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, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.isis.core.commons.debug; 020 021import java.io.PrintWriter; 022import java.io.StringWriter; 023 024public abstract class DebugHtmlStringAbstract implements DebugBuilder { 025 026 private final boolean createPage; 027 private int tableLevel; 028 private boolean isOdd; 029 private boolean titleShown; 030 private boolean endLine; 031 032 public DebugHtmlStringAbstract(final boolean createPage) { 033 this.createPage = createPage; 034 } 035 036 @Override 037 public void concat(final DebugBuilder debug) { 038 appendHtml(debug.toString()); 039 } 040 041 @Override 042 public void append(final int number, final int width) { 043 appendHtml(number + ""); 044 } 045 046 @Override 047 public void append(final Object object) { 048 if (object instanceof DebuggableWithTitle) { 049 DebuggableWithTitle d = (DebuggableWithTitle) object; 050 appendTitle(d.debugTitle()); 051 d.debugData(this); 052 } else { 053 appendHtml(object.toString()); 054 } 055 } 056 057 @Override 058 public void append(final Object object, final int width) { 059 appendHtml(object.toString()); 060 } 061 062 @Override 063 public void appendln() { 064 if (tableLevel > 0) { 065 endLine = true; 066 } else { 067 appendHtml("<p></p>"); 068 } 069 } 070 071 @Override 072 public void blankLine() { 073 if (tableLevel > 0) { 074 appendHtml(row() + "<td class=\"error\" colspan=\"2\" >blank line</td></tr>"); 075 } else { 076 appendHtml("<p>blank line</p>"); 077 } 078 } 079 080 @Override 081 public void appendln(final String label, final boolean value) { 082 appendln(label, String.valueOf(value)); 083 } 084 085 @Override 086 public void appendln(final String label, final double value) { 087 appendln(label, String.valueOf(value)); 088 } 089 090 @Override 091 public void appendln(final String label, final long value) { 092 appendln(label, String.valueOf(value)); 093 } 094 095 @Override 096 public void appendAsHexln(final String label, final long value) { 097 appendln(label, Long.toHexString(value)); 098 } 099 100 @Override 101 public void appendPreformatted(final String label, final String object) { 102 final String value = object == null ? "null" : object.toString(); 103 appendln(label, "<pre>" + value + "</pre>"); 104 }; 105 106 @Override 107 public void appendln(final String label, final Object object) { 108 final String value = object == null ? "null" : object.toString(); 109 appendln(label, value); 110 } 111 112 @Override 113 public void appendln(final String label, final Object[] object) { 114 if (object.length == 0) { 115 appendln(label, "empty array"); 116 } else { 117 appendln(label, object[0]); 118 for (int i = 1; i < object.length; i++) { 119 appendHtml(row() + "<td></td><td>" + object[i] + "</td></tr>"); 120 } 121 } 122 } 123 124 @Override 125 public void startSection(final String title) { 126 startTableIfNeeded(true); 127 appendTitle(title); 128 } 129 130 @Override 131 public void endSection() { 132 endTableIfStarted(); 133 } 134 135 @Override 136 public void indent() { 137 if (tableLevel > 0) { 138 appendHtml(row() + "<td>indented</td><td>"); 139 startTableIfNeeded(true); 140 } 141 } 142 143 @Override 144 public void unindent() { 145 if (tableLevel > 0) { 146 endTableIfStarted(); 147 appendHtml("</td>"); 148 } 149 } 150 151 protected void header() { 152 if (createPage) { 153 appendHtml("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"); 154 appendHtml("<html>"); 155 appendHtml("<head>"); 156 appendHtml("<title>Debug Details</title>"); 157 appendHtml("<style type=\"text/css\">"); 158 appendHtml("body { margin: 15px; }\n" + ".links { background: #ddd; font-size: 80%; padding-bottom:5px; }\n" + ".links > p { display: inline-block; }\n" + "td {vertical-align: top; margin-left: 15px;}\n" + "td.error {color: red; font-style: italic; }\n" + "td.code {white-space: pre; font-family: monospace;}\n" 159 + "th.title {text-align: left; padding: 0.3em 1em; font-style: italic; background: #AED1FF; }\n" + "td.label {width: 16em; text-align: right; padding-right: 1.5em; padding-top: 0.2em; font-size: 80%; font-weight: bold; }\n" 160 + "span.facet-type { font-weight: bold; padding-right: 10px; }\n"); 161 appendHtml("</style>"); 162 appendHtml("</head>"); 163 appendHtml("<body>"); 164 } 165 } 166 167 protected abstract void appendHtml(String html); 168 169 protected void footer() { 170 endTableIfStarted(); 171 if (createPage) { 172 appendHtml("</body>"); 173 appendHtml("</html>"); 174 } 175 } 176 177 @Override 178 public void appendException(final Throwable e) { 179 appendTitle("Exception"); 180 final String message = e.getMessage(); 181 if (message != null) { 182 appendHtml(row() + "<td class=\"error\" colspan=\"2\" >" + message + "</td></tr>"); 183 } 184 causingException(e); 185 appendHtml(row() + "<td class=\"code\" colspan=\"2\" ><pre>"); 186 final StringWriter stringWriter = new StringWriter(); 187 final PrintWriter printWriter = new PrintWriter(stringWriter); 188 e.printStackTrace(printWriter); 189 appendHtml(stringWriter.toString()); 190 appendHtml("</pre></td></tr>"); 191 192 } 193 194 private void causingException(final Throwable throwable) { 195 final Throwable cause = throwable.getCause(); 196 if (cause != null && cause != throwable) { 197 appendHtml(row() + "<td colspan=\"2\" >" + cause.getMessage() + "</td></tr>"); 198 causingException(cause); 199 } 200 } 201 202 @Override 203 public void appendTitle(final String title) { 204 if (tableLevel > 0) { 205 String className = titleShown ? "subtitle" : "title"; 206 appendHtml(row() + "<th class=\""+ className + "\" colspan=\"2\" >" + title + "</th></tr>"); 207 titleShown = true; 208 } else { 209 appendHtml("<h2>" + title + "</h2>"); 210 } 211 } 212 213 private void appendln(final String name, final String value) { 214 startTableIfNeeded(false); 215 appendHtml(row() + "<td class=\"label\">" + name + "</td><td>" + value + "</td></tr>"); 216 } 217 218 private String row() { 219 final String line = (isOdd ? "odd" : "even") + (endLine ? " end-line" : ""); 220 isOdd = !isOdd; 221 endLine = false; 222 return "<tr class=\"" + line + "\">"; 223 } 224 225 private void startTableIfNeeded(final boolean b) { 226 if (tableLevel == 0 || b) { 227 appendHtml("<table class=\"debug\" summary=\"Debug details\" >"); 228 tableLevel++; 229 titleShown = false; 230 } 231 } 232 233 private void endTableIfStarted() { 234 if (tableLevel > 0) { 235 appendHtml("</table>"); 236 tableLevel--; 237 } 238 } 239 240 @Override 241 public void appendPreformatted(final String text) { 242 appendln("<pre>" + text + "</pre>"); 243 } 244 245 @Override 246 public void appendln(final String text) { 247 if (tableLevel > 0) { 248 appendHtml(row() + "<td colspan=\"2\">" + text + "</td></tr>"); 249 } else { 250 appendHtml("<p>" + text + "</p>"); 251 } 252 } 253 254 @Override 255 public void close() { 256 endTableIfStarted(); 257 doClose(); 258 } 259 260 protected abstract void doClose(); 261 262}