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 HtmlDocTemplateBasic implements HtmlDocTemplate { 024 025 @Override /* HtmlDocTemplate */ 026 public void head(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 027 028 String[] head = session.getHead(); 029 for (int i = 0; i < head.length; i++) 030 w.sIf(i > 0).appendln(2, head[i]); 031 032 if (hasStyle(session)) { 033 w.sTag(2, "style").nl(2); 034 style(session, w, o); 035 w.ie(2).eTag("style").nl(2); 036 } 037 if (hasScript(session)) { 038 w.sTag(2, "script").nl(2); 039 script(session, w, o); 040 w.ie(2).eTag("script").nl(2); 041 } 042 } 043 044 @Override /* HtmlDocTemplate */ 045 public void style(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 046 047 int i = 0; 048 for (String s : session.getStylesheet()) 049 w.sIf(i++ > 0).append(3, "@import ").q().append(session.resolveUri(s)).q().appendln(";"); 050 051 if (session.isNoWrap()) 052 w.appendln(3, "div.data * {white-space:nowrap;} "); 053 054 for (String s : session.getStyle()) 055 w.sIf(i > 0).appendln(3, s); 056 } 057 058 @Override /* HtmlDocTemplate */ 059 public void script(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 060 int i = 0; 061 for (String s : session.getScript()) 062 w.sIf(i++ > 0).append(3, s).append('\n'); // Must always append a newline even if whitespace disabled! 063 } 064 065 @Override /* HtmlDocTemplate */ 066 public void body(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 067 068 if (hasHeader(session)) { 069 w.sTag(2, "header").nl(2); 070 header(session, w, o); 071 w.ie(2).eTag("header").nl(2); 072 } 073 074 if (hasNav(session)) { 075 w.sTag(2, "nav").nl(2); 076 nav(session, w, o); 077 w.ie(2).eTag("nav").nl(2); 078 } 079 080 w.sTag(2, "section").nl(2); 081 082 w.sTag(3, "article").nl(3); 083 article(session, w, o); 084 w.ie(3).eTag("article").nl(3); 085 086 if (hasAside(session)) { 087 w.sTag(3, "aside").nl(3); 088 aside(session, w, o); 089 w.ie(3).eTag("aside").nl(3); 090 } 091 092 w.ie(2).eTag("section").nl(2); 093 094 if (hasFooter(session)) { 095 w.sTag(2, "footer").nl(2); 096 footer(session, w, o); 097 w.ie(2).eTag("footer").nl(2); 098 } 099 } 100 101 @Override /* HtmlDocTemplate */ 102 public void header(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 103 // Write the title of the page. 104 String[] header = session.getHeader(); 105 for (int i = 0; i < header.length; i++) 106 w.sIf(i > 0).appendln(3, header[i]); 107 } 108 109 110 @Override /* HtmlDocTemplate */ 111 public void nav(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 112 String[] nav = session.getNav(); 113 if (nav.length > 0) { 114 for (int i = 0; i < nav.length; i++) 115 w.sIf(i > 0).appendln(3, nav[i]); 116 } else { 117 String[] links = session.getNavLinks(); 118 if (links.length > 0) { 119 w.sTag(3, "ol").nl(3); 120 for (String l : links) { 121 w.sTag(4, "li"); 122 if (l.matches("(?s)\\S+\\:.*")) { 123 int i = l.indexOf(':'); 124 String key = l.substring(0, i); 125 String val = l.substring(i+1).trim(); 126 if (val.startsWith("<")) 127 w.nl(4).appendln(5, val); 128 else 129 w.oTag("a").attr("href", session.resolveUri(val), true).cTag().text(key, true).eTag("a"); 130 w.eTag("li").nl(4); 131 } else { 132 w.nl(4).appendln(5, l); 133 w.eTag(4, "li").nl(4); 134 } 135 } 136 w.eTag(3, "ol").nl(3); 137 } 138 } 139 } 140 141 @Override /* HtmlDocTemplate */ 142 public void aside(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 143 String[] aside = session.getAside(); 144 for (int i = 0; i < aside.length; i++) 145 w.sIf(i > 0).appendln(4, aside[i]); 146 } 147 148 @Override /* HtmlDocTemplate */ 149 public void article(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 150 // To allow for page formatting using CSS, we encapsulate the data inside two div tags: 151 // <div class='outerdata'><div class='data' id='data'>...</div></div> 152 w.oTag(4, "div").attr("class","outerdata").append('>').nl(4); 153 w.oTag(5, "div").attr("class","data").attr("id", "data").append('>').nl(5); 154 155 if (o == null) { 156 w.append(6, "<null/>").nl(6); 157 } else if (ObjectUtils.isEmpty(o)){ 158 String m = session.getNoResultsMessage(); 159 if (exists(m)) 160 w.append(6, m).nl(6); 161 } else { 162 session.indent = 6; 163 w.flush(); 164 session.parentSerialize(w, o); 165 } 166 167 w.ie(5).eTag("div").nl(5); 168 w.ie(4).eTag("div").nl(4); 169 } 170 171 @Override /* HtmlDocTemplate */ 172 public void footer(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { 173 String[] footer = session.getFooter(); 174 for (int i = 0; i < footer.length; i++) 175 w.sIf(i > 0).appendln(3, footer[i]); 176 } 177 178 @Override /* HtmlDocTemplate */ 179 public boolean hasStyle(HtmlDocSerializerSession session) { 180 return true; 181 } 182 183 @Override /* HtmlDocTemplate */ 184 public boolean hasScript(HtmlDocSerializerSession session) { 185 return true; 186 } 187 188 @Override /* HtmlDocTemplate */ 189 public boolean hasHeader(HtmlDocSerializerSession session) { 190 return session.getHeader().length > 0; 191 } 192 193 @Override /* HtmlDocTemplate */ 194 public boolean hasNav(HtmlDocSerializerSession session) { 195 return session.getNav().length > 0 || session.getNavLinks().length > 0; 196 } 197 198 @Override /* HtmlDocTemplate */ 199 public boolean hasAside(HtmlDocSerializerSession session) { 200 return session.getAside().length > 0; 201 } 202 203 @Override /* HtmlDocTemplate */ 204 public boolean hasFooter(HtmlDocSerializerSession session) { 205 return session.getFooter().length > 0; 206 } 207 208 private static boolean exists(String s) { 209 return s != null && ! "NONE".equals(s); 210 } 211}