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 org.apache.juneau.internal.*; 016 017/** 018 * A basic template for the HTML doc serializer. 019 * 020 * <p> 021 * This class can be subclassed to customize page rendering. 022 */ 023public class BasicHtmlDocTemplate implements HtmlDocTemplate { 024 025 @Override /* HtmlDocTemplate */ 026 public void writeTo(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 027 w.sTag("html").nl(0); 028 w.sTag(1, "head").nl(1); 029 head(session, w, o); 030 w.eTag(1, "head").nl(1); 031 w.sTag(1, "body").nl(1); 032 body(session, w, o); 033 w.eTag(1, "body").nl(1); 034 w.eTag("html").nl(0); 035 } 036 037 /** 038 * Renders the contents of the <code><xt><head></xt></code> element. 039 * 040 * @param session The current serializer session. 041 * @param w The writer being written to. 042 * @param o The object being serialized. 043 * @throws Exception Any exception can be thrown. 044 */ 045 // TODO - Make protected in 8.0. 046 @Override 047 public void head(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 048 049 String[] head = session.getHead(); 050 for (int i = 0; i < head.length; i++) 051 w.sIf(i > 0).appendln(2, head[i]); 052 053 if (hasStyle(session)) { 054 w.sTag(2, "style").nl(2); 055 style(session, w, o); 056 w.ie(2).eTag("style").nl(2); 057 } 058 if (hasScript(session)) { 059 w.sTag(2, "script").nl(2); 060 script(session, w, o); 061 w.ie(2).eTag("script").nl(2); 062 } 063 } 064 065 /** 066 * Renders the contents of the <code><xt><head></xt>/<xt><style></xt></code> element. 067 * 068 * @param session The current serializer session. 069 * @param w The writer being written to. 070 * @param o The object being serialized. 071 * @throws Exception Any exception can be thrown. 072 */ 073 // TODO - Make protected in 8.0. 074 @Override 075 public void style(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 076 077 int i = 0; 078 for (String s : session.getStylesheet()) 079 w.sIf(i++ > 0).append(3, "@import ").q().append(session.resolveUri(s)).q().appendln(";"); 080 081 if (session.isNowrap()) 082 w.appendln(3, "div.data * {white-space:nowrap;} "); 083 084 for (String s : session.getStyle()) 085 w.sIf(i > 0).appendln(3, s); 086 } 087 088 /** 089 * Renders the contents of the <code><xt><head></xt>/<xt><script></xt></code> element. 090 * 091 * @param session The current serializer session. 092 * @param w The writer being written to. 093 * @param o The object being serialized. 094 * @throws Exception Any exception can be thrown. 095 */ 096 // TODO - Make protected in 8.0. 097 @Override 098 public void script(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 099 int i = 0; 100 for (String s : session.getScript()) 101 w.sIf(i++ > 0).append(3, s).append('\n'); // Must always append a newline even if whitespace disabled! 102 } 103 104 /** 105 * Renders the contents of the <code><xt><body></xt></code> element. 106 * 107 * @param session The current serializer session. 108 * @param w The writer being written to. 109 * @param o The object being serialized. 110 * @throws Exception Any exception can be thrown. 111 */ 112 // TODO - Make protected in 8.0. 113 @Override 114 public void body(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 115 116 if (hasHeader(session)) { 117 w.sTag(2, "header").nl(2); 118 header(session, w, o); 119 w.ie(2).eTag("header").nl(2); 120 } 121 122 if (hasNav(session)) { 123 w.sTag(2, "nav").nl(2); 124 nav(session, w, o); 125 w.ie(2).eTag("nav").nl(2); 126 } 127 128 w.sTag(2, "section").nl(2); 129 130 w.sTag(3, "article").nl(3); 131 article(session, w, o); 132 w.ie(3).eTag("article").nl(3); 133 134 if (hasAside(session)) { 135 w.sTag(3, "aside").nl(3); 136 aside(session, w, o); 137 w.ie(3).eTag("aside").nl(3); 138 } 139 140 w.ie(2).eTag("section").nl(2); 141 142 if (hasFooter(session)) { 143 w.sTag(2, "footer").nl(2); 144 footer(session, w, o); 145 w.ie(2).eTag("footer").nl(2); 146 } 147 } 148 149 /** 150 * Renders the contents of the <code><xt><body></xt>/<xt><header></xt></code> element. 151 * 152 * @param session The current serializer session. 153 * @param w The writer being written to. 154 * @param o The object being serialized. 155 * @throws Exception Any exception can be thrown. 156 */ 157 // TODO - Make protected in 8.0. 158 @Override 159 public void header(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 160 // Write the title of the page. 161 String[] header = session.getHeader(); 162 for (int i = 0; i < header.length; i++) 163 w.sIf(i > 0).appendln(3, header[i]); 164 } 165 166 /** 167 * Renders the contents of the <code><xt><body></xt>/<xt><nav></xt></code> element. 168 * 169 * @param session The current serializer session. 170 * @param w The writer being written to. 171 * @param o The object being serialized. 172 * @throws Exception Any exception can be thrown. 173 */ 174 // TODO - Make protected in 8.0. 175 @Override 176 public void nav(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 177 String[] links = session.getNavLinks(); 178 if (links.length > 0 && ! ArrayUtils.contains("NONE", links)) { 179 w.sTag(3, "ol").nl(3); 180 for (String l : links) { 181 w.sTag(4, "li"); 182 if (l.matches("(?s)\\S+\\:.*")) { 183 int i = l.indexOf(':'); 184 String key = l.substring(0, i); 185 String val = l.substring(i+1).trim(); 186 if (val.startsWith("<")) 187 w.nl(4).appendln(5, val); 188 else 189 w.oTag("a").attr("href", session.resolveUri(val), true).cTag().text(key, true).eTag("a"); 190 w.eTag("li").nl(4); 191 } else { 192 w.nl(4).appendln(5, l); 193 w.eTag(4, "li").nl(4); 194 } 195 } 196 w.eTag(3, "ol").nl(3); 197 } 198 String[] nav = session.getNav(); 199 if (nav.length > 0) { 200 for (int i = 0; i < nav.length; i++) 201 w.sIf(i > 0).appendln(3, nav[i]); 202 } 203 } 204 205 /** 206 * Renders the contents of the <code><xt><body></xt>/<xt><aside></xt></code> element. 207 * 208 * @param session The current serializer session. 209 * @param w The writer being written to. 210 * @param o The object being serialized. 211 * @throws Exception Any exception can be thrown. 212 */ 213 // TODO - Make protected in 8.0. 214 @Override 215 public void aside(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 216 String[] aside = session.getAside(); 217 for (int i = 0; i < aside.length; i++) 218 w.sIf(i > 0).appendln(4, aside[i]); 219 } 220 221 /** 222 * Renders the contents of the <code><xt><body></xt>/<xt><article></xt></code> element. 223 * 224 * @param session The current serializer session. 225 * @param w The writer being written to. 226 * @param o The object being serialized. 227 * @throws Exception Any exception can be thrown. 228 */ 229 // TODO - Make protected in 8.0. 230 @Override 231 public void article(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 232 // To allow for page formatting using CSS, we encapsulate the data inside two div tags: 233 // <div class='outerdata'><div class='data' id='data'>...</div></div> 234 w.oTag(4, "div").attr("class","outerdata").append('>').nl(4); 235 w.oTag(5, "div").attr("class","data").attr("id", "data").append('>').nl(5); 236 237 if (o == null) { 238 w.append(6, "<null/>").nl(6); 239 } else if (ObjectUtils.isEmpty(o)){ 240 String m = session.getNoResultsMessage(); 241 if (exists(m)) 242 w.append(6, m).nl(6); 243 } else { 244 session.indent = 6; 245 w.flush(); 246 session.parentSerialize(w, o); 247 } 248 249 w.ie(5).eTag("div").nl(5); 250 w.ie(4).eTag("div").nl(4); 251 } 252 253 /** 254 * Renders the contents of the <code><xt><body></xt>/<xt><footer></xt></code> element. 255 * 256 * @param session The current serializer session. 257 * @param w The writer being written to. 258 * @param o The object being serialized. 259 * @throws Exception Any exception can be thrown. 260 */ 261 // TODO - Make protected in 8.0. 262 @Override 263 public void footer(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 264 String[] footer = session.getFooter(); 265 for (int i = 0; i < footer.length; i++) 266 w.sIf(i > 0).appendln(3, footer[i]); 267 } 268 269 /** 270 * Returns <jk>true</jk> if this page should render a <code><xt><head></xt>/<xt><style></xt></code> element. 271 * 272 * @param session The current serializer session. 273 * @return A boolean flag. 274 */ 275 // TODO - Make protected in 8.0. 276 @Override 277 public boolean hasStyle(HtmlDocSerializerSession session) { 278 return true; 279 } 280 281 /** 282 * Returns <jk>true</jk> if this page should render a <code><xt><head></xt>/<xt><script></xt></code> element. 283 * 284 * @param session The current serializer session. 285 * @return A boolean flag. 286 */ 287 // TODO - Make protected in 8.0. 288 @Override 289 public boolean hasScript(HtmlDocSerializerSession session) { 290 return true; 291 } 292 293 /** 294 * Returns <jk>true</jk> if this page should render a <code><xt><body></xt>/<xt><header></xt></code> 295 * element. 296 * 297 * @param session The current serializer session. 298 * @return A boolean flag. 299 */ 300 // TODO - Make protected in 8.0. 301 @Override 302 public boolean hasHeader(HtmlDocSerializerSession session) { 303 return session.getHeader().length > 0; 304 } 305 306 /** 307 * Returns <jk>true</jk> if this page should render a <code><xt><body></xt>/<xt><nav></xt></code> 308 * element. 309 * 310 * @param session The current serializer session. 311 * @return A boolean flag. 312 */ 313 // TODO - Make protected in 8.0. 314 @Override 315 public boolean hasNav(HtmlDocSerializerSession session) { 316 return session.getNav().length > 0 || session.getNavLinks().length > 0; 317 } 318 319 /** 320 * Returns <jk>true</jk> if this page should render a <code><xt><body></xt>/<xt><aside></xt></code> 321 * element. 322 * 323 * @param session The current serializer session. 324 * @return A boolean flag. 325 */ 326 // TODO - Make protected in 8.0. 327 @Override 328 public boolean hasAside(HtmlDocSerializerSession session) { 329 return session.getAside().length > 0; 330 } 331 332 /** 333 * Returns <jk>true</jk> if this page should render a <code><xt><body></xt>/<xt><footer></xt></code> 334 * element. 335 * 336 * @param session The current serializer session. 337 * @return A boolean flag. 338 */ 339 // TODO - Make protected in 8.0. 340 @Override 341 public boolean hasFooter(HtmlDocSerializerSession session) { 342 return session.getFooter().length > 0; 343 } 344 345 private static boolean exists(String s) { 346 return s != null && ! "NONE".equals(s); 347 } 348}