1
2
3
4
5
6
7
8
9
10
11
12 package org.hyphenType.documentation.lib;
13
14 import java.io.PrintStream;
15 import java.lang.annotation.ElementType;
16 import java.lang.annotation.Retention;
17 import java.lang.annotation.RetentionPolicy;
18 import java.lang.annotation.Target;
19
20 import org.hyphenType.datastructure.Options;
21 import org.hyphenType.datastructure.parser.option.StructureOption;
22 import org.hyphenType.datastructure.parser.option.StructureOptionArgument;
23 import org.hyphenType.datastructure.parser.simple.StructureSimpleArgument;
24 import org.hyphenType.documentation.DocumentationFormatterEngine;
25 import org.hyphenType.exit.StatusCode;
26 import org.hyphenType.lexerparser.LexerParser;
27 import org.hyphenType.util.soc.StringParsingError;
28
29
30
31
32
33
34
35
36
37 public class HTMLFormatterEngine<T extends Options<?>> extends DocumentationFormatterEngine<T, HTMLFormatterEngine.HTMLFormatter> {
38
39
40
41
42 @Retention(RetentionPolicy.RUNTIME)
43 @Target(ElementType.TYPE)
44 public @interface HTMLFormatter {
45
46
47
48 boolean bodyOnly() default false;
49
50
51
52
53 boolean addW3CLogo() default false;
54
55
56
57
58 boolean addHyphenTypeLogo() default false;
59
60
61
62
63 String colorA() default "#DDDDDD";
64
65
66
67
68 String colorB() default "#FFFFDD";
69
70
71
72
73 String usage() default "usage";
74
75
76
77
78 String options() default "options";
79
80
81
82
83 String option() default "option";
84
85
86
87
88 String statusCode() default "status code";
89
90
91
92
93 String meaning() default "Meaning";
94 }
95
96 @SuppressWarnings("unchecked")
97 @Override
98 public final void printDocumentation(final PrintStream pw, final LexerParser<T> lexPar, final HTMLFormatter annotation) {
99
100 try {
101
102 if (!annotation.bodyOnly()) {
103 pw.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
104 pw.println("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">");
105 pw.println("\t<head>");
106 pw.println("\t\t<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />");
107 pw.println("\t\t<title>Command line documentation</title>");
108 pw.println("\t\t<style type=\"text/css\">");
109 pw.println("\t\t\tbody {font-family:Verdana;}");
110 pw.println("\t\t\ttr.r0 {");
111 pw.println("\t\t\t\tbackground-color: " + annotation.colorA() + ";");
112 pw.println("\t\t\t}");
113 pw.println("\t\t\ttr.r1 {");
114 pw.println("\t\t\t\tbackground-color: " + annotation.colorB() + ";");
115 pw.println("\t\t\t}");
116 pw.println("\t\t\timg {border: none}");
117 pw.println("\t\t</style>");
118 pw.println("\t</head>");
119 pw.println("\t<body>");
120 }
121
122 pw.println("\t\t<p>" + annotation.usage() + ": program [" + annotation.options() + "] ");
123
124 pw.print("\t\t");
125
126 for (StructureSimpleArgument simpleArgument : lexPar.getSimpleArguments()) {
127 if (!simpleArgument.isMandatory()) {
128 pw.print("\t\t[");
129 }
130 pw.print(getOptionsInterfaceValue(simpleArgument.getName(), simpleArgument.getName()));
131 if (simpleArgument.method.getReturnType().isArray()) {
132 pw.print("...");
133 }
134 if (!simpleArgument.isMandatory()) {
135 pw.print("]");
136 }
137 pw.print(" ");
138 }
139
140 pw.println("<br/>");
141 pw.println("\t\t\t<br/>");
142 pw.println("\t\t\t" + getOptionsInterfaceValue("", lexPar.getArgsObject().description()));
143 pw.println("\t\t\t<br/>");
144 pw.println("\t\t\t<br/>");
145 pw.println("\t\t</p>");
146 pw.println("\t\t<table cellspacing=\"0\" rules=\"rows\" frame=\"hsides\">");
147 pw.println("\t\t\t<tr>");
148 pw.println("\t\t\t\t<td>");
149 pw.println("\t\t\t\t\t<strong>" + annotation.option() + "</strong>");
150 pw.println("\t\t\t\t</td>");
151 pw.println("\t\t\t\t<td>");
152 pw.println("\t\t\t\t\t ");
153 pw.println("\t\t\t\t</td>");
154 pw.println("\t\t\t\t<td>");
155 pw.println("\t\t\t\t\t<strong>" + annotation.meaning() + "</strong>");
156 pw.println("\t\t\t\t</td>");
157 pw.println("\t\t\t</tr>");
158
159 int x = 0;
160
161 for (StructureOption parsedOption : lexPar.getParsedOptions()) {
162
163 x = (x + 1) % 2;
164
165 pw.println("\t\t\t<tr class=\"r" + x + "\">");
166 pw.println("\t\t\t\t<td>");
167
168 String entry = " ";
169 for (String alternative : parsedOption.alternatives) {
170 if (entry.contains(lexPar.getArgsObject().singleHyphen())) {
171 entry += ", ";
172 }
173 if (lexPar.getArgsObject().doubleHyphenInLongOptions() && alternative.length() > 1) {
174 entry += lexPar.getArgsObject().doubleHyphen();
175 } else {
176 entry += lexPar.getArgsObject().singleHyphen();
177 }
178 entry += alternative;
179 if (parsedOption.value != null) {
180 if (!parsedOption.value.mandatory) {
181 entry += "[";
182 }
183 entry += lexPar.getArgsObject().equals() + parsedOption.value.name;
184 if (!parsedOption.value.mandatory) {
185 entry += "]";
186 }
187 }
188 }
189
190 for (StructureOptionArgument argument : parsedOption.arguments) {
191 entry += " ";
192 if (!argument.isMandatory()) {
193 entry += "[";
194 } else {
195 entry += "<";
196 }
197 entry += argument.getName();
198 if (argument.method.getReturnType().isArray()) {
199 entry += "...";
200 }
201 if (!argument.isMandatory()) {
202 entry += "]";
203 } else {
204 entry += ">";
205 }
206 }
207
208 pw.println("\t\t\t\t\t<code>" + entry + "</code>");
209 pw.println("\t\t\t\t</td>");
210 pw.println("\t\t\t\t<td>");
211 pw.println("\t\t\t\t\t ");
212 pw.println("\t\t\t\t</td>");
213 pw.println("\t\t\t\t<td>");
214
215 String optionDocumentation = getOptionsInterfaceValue(parsedOption.method.getName(), parsedOption.description);
216 pw.println("\t\t\t\t\t" + optionDocumentation);
217 pw.println("\t\t\t\t</td>");
218 pw.println("\t\t\t</tr>");
219 }
220
221 pw.println("\t\t</table>");
222
223 if (lexPar.getArgsObject().documentStatusCodes()) {
224
225 pw.println("\t\t<p><br/><br/></p>");
226 pw.println("\t\t<table cellspacing=\"0\" rules=\"rows\" frame=\"hsides\">");
227 pw.println("\t\t\t<tr>");
228 pw.println("\t\t\t\t<td>");
229 pw.println("\t\t\t\t\t<strong>" + annotation.statusCode() + "</strong>");
230 pw.println("\t\t\t\t</td>");
231 pw.println("\t\t\t\t<td>");
232 pw.println("\t\t\t\t\t ");
233 pw.println("\t\t\t\t</td>");
234 pw.println("\t\t\t\t<td>");
235 pw.println("\t\t\t\t\t<strong>" + annotation.meaning() + "</strong>");
236 pw.println("\t\t\t\t</td>");
237 pw.println("\t\t\t</tr>");
238 pw.println();
239
240 for (StatusCode statusCode : lexPar.getArgsObject().statusCodeEnum().getEnumConstants()) {
241 Enum<?> enumConstant = Enum.valueOf((Class<? extends Enum>) lexPar.getArgsObject().statusCodeEnum(), statusCode.toString());
242
243 x = (x + 1) % 2;
244
245 pw.println("\t\t\t<tr class=\"r" + x + "\">");
246 pw.println("\t\t\t\t<td align=\"right\">");
247 pw.println("\t\t\t\t\t" + enumConstant.ordinal());
248 pw.println("\t\t\t\t</td>");
249 pw.println("\t\t\t\t<td>");
250 pw.println("\t\t\t\t\t ");
251 pw.println("\t\t\t\t</td>");
252 pw.println("\t\t\t\t<td>");
253 pw.println("\t\t\t\t\t" + getStatusCodeUserDescription(enumConstant));
254 pw.println("\t\t\t\t</td>");
255 pw.println("\t\t\t</tr>");
256 }
257 pw.println("\t\t</table>");
258 }
259
260 pw.println("\t\t<p>");
261
262 if (annotation.addW3CLogo()) {
263 pw.println("\t\t\t<a href=\"http://validator.w3.org/check?uri=referer\"><img src=\"data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAABUFvrSAAADAFBMVEUBAAAIBgMMCQQLCwsSDgYXEgkaFQoUFBQcHB" + "wlHQ4rIhEwJhM2KxU7Lxc9MBgjIyMoKCg0MzI7OztBNBpOPh5OSz9TQiFeSyVkUChqVCpuWCx1Rzl0XC5+ZDFOTk5S" + "T0tWUk1VVVVcXFxqXUplZWVra2twcHB7e3sAWpwIX58JYJ8OY6ERZaIVaKQaa6Yebaghb6klcqopdawxea82fbE4fr" + "I+grRFhrZMi7pVkb1alL9dlsBkm8NoncRtocZ0pcl8qsyWBAOZAACcCASIIBmdNiegDge3PB6mPiqBZzODaDSKbjaO" + "cTiUdjuXeDyaez26QiG/TCaAeWihclPATifBUCjIXy/QbzfWej3Yfj+KgWWjgkGui0WxjUa0gVi3kkm6lEq+mEyjkm" + "uzn2e7pnLFnU7eikXOpFHRp1PVqlXarlfesVjjlUrmm03poFDtqVTitFrmuFzqu13ywWD7xWL+y2WDg4OXl5eYmJip" + "pZ61rZisrKy0tLS/v7+Crs6FsNCLtNKQt9SWu9aYvNebvtifwdqjw9uox92ryd6yzeG20OPCwsLMzMzU1NTA1ufG2u" + "jN3+zT4+7d6fL/7Mbn5+fs7Ozl7vXp8fbu9Pj09PTy9/r1+Pv+/v7MzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
264 + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADn" + "4rtgAAAAnnRSTlP///////////////////////////////////////////////////////////////////////////" + "//////////////////////////////////////////////////////////////////////////////////////////" + "////////////////////////////////////////////AD6H4/gAAAABYktHRP+lB/LFAAAACXBIWXMAAABIAAAASA" + "BGyWs+AAADSUlEQVRIx+2WaU8TURSGzyCLQEUxiFYtCEo8Da3sYglQbDUaluISV6pYFdsyop1Or8ElSgg2RSjgArSZ" + "63/13JkOXRBZgn7yTXpmyzwz857lFhb3XW9/CsEi317f2c71/OnZ/+C9gSdDKmNySI2GorQNxiaDpFA4FgrS+WgoxF" + "hwck/gMTjBwmCJ+WCYMQso5SBUoQCcZKwGgClg2QSOt7jp7pnWGQFJ2e0tpFYX5+k3TUn+QTOsqAV/hRRmJngiYAVr" + "YILAkipT+C34GzqJ+AW7BDiBhga4VgdwIFmdNMBKMcAQI3Ctz1cOCmPD4hEKVBX5TpdYfg/m7bhC0YHrFHvQtbY2h8"
265 + "40fw9Hzh8tO7CaSZ6V3k2AdWXBNdaKosGtwG78SLED4xSd+I1rbWK37ii5cO58pirCUglYBXhIjVlywWGQoluBl7CT" + "83VE8nUZ28lu3ZUycUlLZ8CVUrgGnpgeR7JgZrUxHVzh9/tjAuzxbFRFM7nwGbGZ8wF083UHLlPqDuZWxSAZrBSXqm" + "byGBuBEQNM0sFCUQJf8QiyAXbRp7uwA5fI7iXei9ifotzlgiMy3R+NqKpMRiv6gUwVzfTAlAiLyUJkxVWPUAYcR5fW" + "fCGB7jV00GOciJ0an95T5133GDLAKXTMY1/K3j6HPeJ42YEJvrAX8M0M1+y8LvJhnnejURmc92HvH2aFGtuWa4I/Id" + "o1qgbElH48j235YNkiwbhxc6QKpJN56NiN18bOnQ2uCV5BvCRaEC8aqAS2rBp76bSRPFutCT4No8chkMu95vG+ynIv" + "e3KHUAvO6i04w2d7dCu6Fwxy00LGCpsJrixlQbAVfL/35Qb3VN5068M1vQW/UrG5U3EHxrXGH4IrJTfAxluqUMWicC" + "jLva/zvC8Mf72388fmfIeIS61UIU60o2jFxbKGxsMwzQvfuKScyTREcxz2ZOV9XDCPtY/6ZoB+X1/udzl6Rw2RDWfV" + "7ngceonFxXIqMgj83eXey3Fe7HfRh0bAlondZQJKgXM2rsrsmd2rXK4j6ZHx8PMAmhM/y2CO1oH7vmdx9X0wfZLj7v" + "0q/8Orcv7D8T039s/8VH7bVu2c718NbJrhuBzq2leo3nTlTX62DfwGZkKiGotSUXQAAAABJRU5ErkJggg==\" " + "alt=\"Valid XHTML 1.0 Strict\" height=\"31\" width=\"88\" /></a>");
266 }
267
268 if (annotation.addHyphenTypeLogo()) {
269 pw.println("\t\t\t<a href=\"http://hyphenType.org\"><img alt=\"hyphenType\" src=\"data:image/png;base64," + "iVBORw0KGgoAAAANSUhEUgAAAFQAAAAkCAYAAAAXSR0AAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEnQAABJ0BfD" + "RroQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAA15SURBVGiB7Zp5UBdXtsc/v/6xaNgk4rDK" + "T0UT/ImIigsOyUDUjHF5SHADgxj35cUk46QkMS9xcFIPLevlaWb8GTNJZUajMWJiKUoIgkkUpBRHVBR3ERUkrggosp" + "33R0NDsyeaMpN536pbt/ts9/bt0+ee2/caVqxYIf7+/gAYaAQRPb32vk1ac7ot0dqgN6QZGrXXGr1FWuM+t9Nee2TT" + "tm3DkJSUJGazmYyMjCbCv1Z0ys/H8cqVR2av64QJdH32WaKHD8cKICMjg8jIyEfWwC8d8cCSR2hv/717dH32WRRFQX" + "mEdn+RiIqKIjU1tWUBNzfIy1Prh4TRaPz1D6i9vT1eXl4tCxiNYDKBldVDt9XEQ21sbDAajRgMBnr27Ennzp2bVXR2" + "dsZsNmNjY6Ojd+jQAYOhfhqxtrZGUeqbsLKywtraWqfj6OiIn58fdnZ2Orq1tTVWDR6yoV0Ak8lEz549dfYbtmM2m/" + "Hw8Gi2/y3CxgbMZrC1bdgRtTQnazTqSIrBAElJSbJ582YBJCsrS7Zu3Sp5eXlSVVUlIiLLly8XQADp2LGjbNiwQURE" + "7t69K6WlpRIdHS2AKIoiN2/elAkTJmjyJ0+elLi4OO3+888/l5UrVwogHTp0kI8++kiqq6slLy9PKioqZMmSJTrZDz"
270 + "/8UFatWiXXr1+Xc+fOCSD9+/eXU6dOye3bt+X27dty9uxZ6devn6YXEhIiRUVFUlFRIaWlpVJYWCinT5/W+IDEq/Oy" + "Wjw9RURE/vIXkXv3RKqqRIqLRZ57TuUvWCBy6ZKI0Viv4+YmUlEhMnCgCMi+mTNFRGTuuHHS5PV6eHgQFhaGvb09r7" + "76Km+//TYDBgwAYMmSJQwbNowhQ4bg4uLC4sWL+eSTTzCbzdTU1LB3716Cg4MB8PX1xWQyMXHiRM12UFAQaWlpAMTG" + "xtK/f398fHzo1q0bISEhvPfee9SlcAAxMTFUVlYSERHBSy+9hK2tLdu2bWPTpk24u7vj7u5OSkoKFosFUL19y5YtfP" + "XVV5hMJhwcHFi/fn37vFMEevVSP//kZPj4YzUMbNgAzs4wZky97OzZcPiwWhp6qKLA1408dOHChbq3ee3aNVm6dKkA" + "cv78eYmPj9fx8/PzNS+eP3++HDp0SAB56623JD4+XgoLC8XPz088PDykoqJC7OzsBJArV67I0qVLJSAgQCu5ubmyaN" + "EizUNXr16ta2v06NFSXFwsgwcP1nSioqKkpqZGOnbsKFOnTpXKykpxcnLSdObMmdM+D/XyqqcNGqTS/PzU+7VrRZKS" + "1GsrK5ErV0SiojT5Og/9z/BwaTMS5+Tk4OrqCoC3tzfp6ek6fnp6Ot7e3gCkpqayZs0a7OzsePHFF5k9ezb29vZMmD" + "CBY8eOcfDgQcrKyujQoQOenp6Eh4czcuRIzVZRURFlZWXafU1Nja6tnj17YjAYWLlypY7+/fff4+DggK+vL9nZ2RQX" + "F7f1WK3jxAm1dnWFnBxYuxaOHoUePaB/f9VzExKaqClGI60OqKIoBAQEkJiYCMD169cxm83s3LlTk+nTpw/ffPMNAG"
271 + "fOnKGwsJBJkybRqVMnjhw5whdffIHFYsHOzk773MvLyykuLmbZsmWa7fagqKiI0tJSQkJCmuXfvXuXrl27tttei+jX" + "T60vXlTrnBxIT4e5cyEwENavh4qKJmrG5vLQulnYYDAQHR2No6Mju3btAiAlJYXw8HDs7e0BCAgIoG/fvqSkpGj6aW" + "lpLF++nITaN7h//36cnZ2JjIzUBhRg9+7dxMbG6mZ3b29vzGZzi89Z54nz58/X0UeNGgWoCxRXV1dGjBihPcvgwYNb" + "tKdDXRZhZQVTp8LJk/UDCvDXv8K8efDMM7BuXQsmDE1jaHl5uWRmZsq5c+eksrJSXnnlFS32eHp6yokTJ+TWrVuSnJ" + "ws1dXVYrFYdPEpOjpaREQCAwM12gcffCD3798XW1tbjebm5iaZmZly7do1SUxM1NoODw/XYuj777+vsw3IpEmT5M6d" + "O3L48GFJTEyUvLw8KSoq0vh1WUh2drYUFhZKdnZ2+2JoYaHIzp0iBQUit2+LBAfXy4CItbVIUZHIli16eoMY+kZUlB" + "i+TkqS23fuEBkZSVZWFhs3biQ3N5fOnTtz4MABLjZ8S6i5ZmhoKO7u7hw9epTDjWY6e3t7Bg4cyHfffafRXF1d8fb2" + "5tChQzpZRVEYOnQoPj4+lJWVkZWVRX5+PgBms5kHDx5w/vz5Jp7g4uLC4MGD6dKlC1euXCE9PZ3y8nLNS4YPH46Xlx" + "cZGRmUlJTQtWtXDh48qOnrlp42NjBsGJw/DyEhUFMDqalw7Zq+UWdnuHwZXngB9u3TsfbPnEnw3/5GbHR027P8r7Ho" + "PLS9ZckSkezsZnl1HvrmtGn6PLSkpIQHDx408Yh/exiNEB0Nq1e3LqYo6ixvMpmYPHky62qD7eTJk3/+Tj5GPJGfz4"
272 + "GrV3+c0ujRal2bIjaEQ+1iRFEUrBAhKCiIoKCgh+3nvz2UOg8tLIYjlx93dx4OfW7lYHoS8PN7bH3QEvsjl+GNBOjW" + "WU3HLt74eRp8wgb6eMDhS1Ajj9b2p3kJmLrxeAe0zkPrEBMEtlbw1vafp0HvJ+HT6TDgz/Cg6tHb37NnD3/c3nLnZ8" + "yYwaJFix59w7UwGo1YNdkY+xeGr68vsbWrpEuXLhEbG8u6detwcnICaHUV9ihgMBiaX8v36AIje8Pd+7DzGJQ+AKMC" + "EQPguzNQdLdettdv1LI7B3zdwN0Jzv6g6tt3gG9OwulGObKNFYz1B49OkHwCzhTp+d1d4LmnodMTcPwqpOSibUK+4A" + "enrqntDOoGOVfh2zMqz8vLiylTpgCQnZ1NbGwsYWFhuLm5UVBQwM6dO+ndu7fuJ3dqaiqKohAaGkpycjKdOnVCURR2" + "796Nra0t06ZN0/2oLi8v57PPPiM3NxdPT0+mTZum/Yhvdi0/tAdYosDUGcIC4OtXwcoI1TUw2g9eHqaX/+Pz4OepXg" + "f3hPfGw9+ng9kdxvjBppnqgDfEltnwvBm8OsEXc2B033re756CzbPUWCsCsaPgDyPq+QtD4MOX4I3nwcVe5a9uR5bn" + "7OzMm2++yZdffqnRKioqiIqK4sYNddKwWCxEREQQGRnJ2bNnWblyJUOGDNFy8+LiYgIDA7FYLDg4OLB9+3b8/f2prK" + "wEmomhAPm3YN5nUF6peuXeP8AgExy4AJsPwZ/Gwf+mqnwvZwjqAX/eXa9/oxSmfgwl5ar+x9Mg5GnVa+uwOAFyC9Xr" + "q3fg+d6w+7gq/84YWJUCCbUr2uST8MEU+J899V6alAPv71Gve/1GfSnH29gd69ixIy+//DIWi0XLs7du3Yq1tTXh4e"
273 + "GaXHBwMBs3bsTKyorS0lK8vb3JyMggNDSU+Ph4XF1dtU2/d999l759+/Ltt98ycuTI5jfpCu6ogwWqV+bfAnOtx6ee" + "Unlja3+qTwqE9PNw+Va9/q0ydTDr9A/mwdDu+jYuXK+/vnij3r73k+DmpHp37Ci1jPNXPdHsrtfRbN1QQ0jHZrZ9Gm" + "PevHns27eP3NxcANauXcvcuXN1e1fdunXT7u3t7RkyZIg2gHv37kVEeO2117QCsGPHDqBBYt8aqmrqT1xUVUPCPyFq" + "EOw4Ci/2h9gvW1WntFwdpJZQ3cC+8xNqfaJApdfhnR2q57ek31706tWLESNGYLFYmDFjBllZWboQ0BycnJy4fFlN0m" + "/cuEFoaCgBAQEaPyAggO7dVY8xNPfJt4Wth2HOM7Dk9+qkld70Z5AOQT56j2wNeTfV+nSROtn8HFiwYAExMTHcvHmT" + "iRMnarsRzUFESE1NZfHixQA89dRT2NraMn369Gblm42hbaHoLuw9DVMGwYqvaeLgro4Q0BWK70NYPxjSHWb9o322b5" + "Wpnv/f4+FPiWrc9X4S/qMf/CNTH1p+KsaOHYujoyObNm3iwIEDTfjHjh3j+PHjlJeXs2bNGqqrq5k1axYAixcvZtSo" + "UfTu3ZuIiAhKSkpIS0ujqqqKhQsXqnloQ2N37oONfquZG6Vq2tQQKbnwWx/4Krtph22t4L/GqJPF5dtqSPin+ouTym" + "o1Rjd8B/cq9WlY3C5Y8DtYNQG6OKgvJvOC+jUA/FAC9xrtPhTcafpibWxsMJlMGBvtnRuNRsLCwsjMzGTo0KFN+l9Q" + "UMC4ceO4evUqgYGBpKam4uLiAsDw4cNJSEjgnXfe4fXXX0dRFPz9/YmLiwNUDzUk79olVd6jeaPpnlOLWD0ZbpZBXK"
274 + "PtoFnBauo0/VN1CdtGeG4T1kb1JbQHn+YtY1A3YNmyVuWqqqrw8fEhLi6OmJgYHW/8+PH4+voSHx+PiDQ5XNHYjqIo" + "uoMWn8TF/fijOF7OEPo0bDrYutzDDia0fzB/DLZt28a9e/e0BUBLaG0wQT2d0vjUyk+KoV7OsCYNzv3QlJdT0PRz/K" + "WhtLSUNWvWYNvwuE0txo0b1+ok1Ra0T77vb0f//++7R4CNK1aoP0fcndTyr43HN5B1UBQFQ8zkyTXHTp40tPdodENa" + "c0esm6MrBoPaWG2tGAwYDAaMjWgNa4PBoLtuTlZHry2t2vuJbbdop3ZSqqPduXCB/wPneX1TjWdPrAAAAABJRU5Erk" + "Jggg==\" /></a>");
275 }
276 pw.println("\t\t</p>");
277
278 if (!annotation.bodyOnly()) {
279 pw.println("\t</body>");
280 pw.println("</html>");
281 }
282
283 } catch (StringParsingError e) {
284 e.printStackTrace();
285 }
286 }
287 }