001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.html; 018 019import java.io.*; 020import java.lang.reflect.*; 021import java.nio.charset.*; 022import java.util.*; 023import java.util.function.*; 024 025import org.apache.juneau.*; 026import org.apache.juneau.commons.collections.FluentMap; 027import org.apache.juneau.httppart.*; 028import org.apache.juneau.serializer.*; 029import org.apache.juneau.svl.*; 030 031/** 032 * Context object that lives for the duration of a single serialization of {@link HtmlSerializer} and its subclasses. 033 * 034 * <p> 035 * See {@link Serializer} for details. 036 * 037 * <h5 class='section'>Notes:</h5><ul> 038 * <li class='warn'>This class is not thread safe and is typically discarded after one use. 039 * </ul> 040 * 041 * <h5 class='section'>See Also:</h5><ul> 042 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HtmlBasics">HTML Basics</a> 043 044 * </ul> 045 */ 046public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession { 047 /** 048 * Builder class. 049 */ 050 public static class Builder extends HtmlStrippedDocSerializerSession.Builder { 051 052 private HtmlDocSerializer ctx; 053 054 /** 055 * Constructor 056 * 057 * @param ctx The context creating this session. 058 */ 059 protected Builder(HtmlDocSerializer ctx) { 060 super(ctx); 061 this.ctx = ctx; 062 } 063 064 @Override /* Overridden from Builder */ 065 public <T> Builder apply(Class<T> type, Consumer<T> apply) { 066 super.apply(type, apply); 067 return this; 068 } 069 070 @Override 071 public HtmlDocSerializerSession build() { 072 return new HtmlDocSerializerSession(this); 073 } 074 075 @Override /* Overridden from Builder */ 076 public Builder debug(Boolean value) { 077 super.debug(value); 078 return this; 079 } 080 081 @Override /* Overridden from Builder */ 082 public Builder fileCharset(Charset value) { 083 super.fileCharset(value); 084 return this; 085 } 086 087 @Override /* Overridden from Builder */ 088 public Builder javaMethod(Method value) { 089 super.javaMethod(value); 090 return this; 091 } 092 093 @Override /* Overridden from Builder */ 094 public Builder locale(Locale value) { 095 super.locale(value); 096 return this; 097 } 098 099 @Override /* Overridden from Builder */ 100 public Builder mediaType(MediaType value) { 101 super.mediaType(value); 102 return this; 103 } 104 105 @Override /* Overridden from Builder */ 106 public Builder mediaTypeDefault(MediaType value) { 107 super.mediaTypeDefault(value); 108 return this; 109 } 110 111 @Override /* Overridden from Builder */ 112 public Builder properties(Map<String,Object> value) { 113 super.properties(value); 114 return this; 115 } 116 117 @Override /* Overridden from Builder */ 118 public Builder property(String key, Object value) { 119 super.property(key, value); 120 return this; 121 } 122 123 @Override /* Overridden from Builder */ 124 public Builder resolver(VarResolverSession value) { 125 super.resolver(value); 126 return this; 127 } 128 129 @Override /* Overridden from Builder */ 130 public Builder schema(HttpPartSchema value) { 131 super.schema(value); 132 return this; 133 } 134 135 @Override /* Overridden from Builder */ 136 public Builder schemaDefault(HttpPartSchema value) { 137 super.schemaDefault(value); 138 return this; 139 } 140 141 @Override /* Overridden from Builder */ 142 public Builder streamCharset(Charset value) { 143 super.streamCharset(value); 144 return this; 145 } 146 147 @Override /* Overridden from Builder */ 148 public Builder timeZone(TimeZone value) { 149 super.timeZone(value); 150 return this; 151 } 152 153 @Override /* Overridden from Builder */ 154 public Builder timeZoneDefault(TimeZone value) { 155 super.timeZoneDefault(value); 156 return this; 157 } 158 159 @Override /* Overridden from Builder */ 160 public Builder unmodifiable() { 161 super.unmodifiable(); 162 return this; 163 } 164 165 @Override /* Overridden from Builder */ 166 public Builder uriContext(UriContext value) { 167 super.uriContext(value); 168 return this; 169 } 170 171 @Override /* Overridden from Builder */ 172 public Builder useWhitespace(Boolean value) { 173 super.useWhitespace(value); 174 return this; 175 } 176 } 177 178 private static final VarResolver DEFAULT_VR = VarResolver.create().defaultVars().vars(HtmlWidgetVar.class).build(); 179 180 /** 181 * Creates a new builder for this object. 182 * 183 * @param ctx The context creating this session. 184 * @return A new builder. 185 */ 186 public static Builder create(HtmlDocSerializer ctx) { 187 return new Builder(ctx); 188 } 189 190 private final HtmlDocSerializer ctx; 191 192 /** 193 * Constructor. 194 * 195 * @param builder The builder for this object. 196 */ 197 protected HtmlDocSerializerSession(Builder builder) { 198 super(builder); 199 ctx = builder.ctx; 200 addVarBean(HtmlWidgetMap.class, ctx.getWidgets()); 201 } 202 203 /** 204 * Returns the {@link HtmlDocSerializer.Builder#navlinks(String...)} setting value in this context. 205 * 206 * @return 207 * The {@link HtmlDocSerializer.Builder#navlinks(String...)} setting value in this context. 208 * <jk>null</jk> if not specified. 209 * Never an empty map. 210 */ 211 public final String[] getNavLinks() { return ctx.navlinks; } 212 213 /** 214 * Calls the parent {@link #doSerialize(SerializerPipe, Object)} method which invokes just the HTML serializer. 215 * 216 * @param out 217 * Where to send the output from the serializer. 218 * @param o The object being serialized. 219 * @throws Exception Error occurred during serialization. 220 */ 221 public void parentSerialize(Object out, Object o) throws Exception { 222 try (var pipe = createPipe(out)) { 223 super.doSerialize(pipe, o); 224 } 225 } 226 227 @Override /* Overridden from SerializerSession */ 228 protected VarResolverSession createDefaultVarResolverSession() { 229 return DEFAULT_VR.createSession(); 230 } 231 232 @Override /* Overridden from Serializer */ 233 protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException { 234 235 try (var w = getHtmlWriter(out)) { 236 try { 237 getTemplate().writeTo(this, w, o); 238 } catch (Exception e) { 239 throw new SerializeException(e); 240 } 241 } 242 } 243 244 /** 245 * Performs an action on all widgets defined in his session. 246 * 247 * @param action The action to perform. 248 * @see HtmlDocSerializer.Builder#widgets(Class...) 249 * @return This object. 250 */ 251 protected final HtmlDocSerializerSession forEachWidget(Consumer<HtmlWidget> action) { 252 ctx.forEachWidget(action); 253 return this; 254 } 255 256 /** 257 * Aside section contents. 258 * 259 * @see HtmlDocSerializer.Builder#aside(String...) 260 * @return 261 * The overridden contents of the aside section on the HTML page. 262 */ 263 protected final String[] getAside() { return ctx.aside; } 264 265 /** 266 * Aside section contents float. 267 * 268 * @see HtmlDocSerializer.Builder#asideFloat(AsideFloat) 269 * @return 270 * The location of where to place the aside section. 271 */ 272 protected final AsideFloat getAsideFloat() { return ctx.asideFloat; } 273 274 /** 275 * Footer section contents. 276 * 277 * @see HtmlDocSerializer.Builder#footer(String...) 278 * @return 279 * The overridden contents of the footer section on the HTML page. 280 */ 281 protected final String[] getFooter() { return ctx.footer; } 282 283 /** 284 * Additional head section content. 285 * 286 * @see HtmlDocSerializer.Builder#head(String...) 287 * @return 288 * HTML content to add to the head section of the HTML page. 289 */ 290 protected final String[] getHead() { return ctx.head; } 291 292 /** 293 * Header section contents. 294 * 295 * @see HtmlDocSerializer.Builder#header(String...) 296 * @return 297 * The overridden contents of the header section on the HTML page. 298 */ 299 protected final String[] getHeader() { return ctx.header; } 300 301 /** 302 * Nav section contents. 303 * 304 * @see HtmlDocSerializer.Builder#nav(String...) 305 * @return 306 * The overridden contents of the nav section on the HTML page. 307 */ 308 protected final String[] getNav() { return ctx.nav; } 309 310 /** 311 * Page navigation links. 312 * 313 * @see HtmlDocSerializer.Builder#navlinks(String...) 314 * @return 315 * Navigation links to add to the HTML page. 316 */ 317 protected final String[] getNavlinks() { return ctx.navlinks; } 318 319 /** 320 * No-results message. 321 * 322 * @see HtmlDocSerializer.Builder#noResultsMessage(String) 323 * @return 324 * The message used when serializing an empty array or empty list. 325 */ 326 protected final String getNoResultsMessage() { return ctx.getNoResultsMessage(); } 327 328 /** 329 * Javascript code. 330 * 331 * @see HtmlDocSerializer.Builder#script(String...) 332 * @return 333 * Arbitrary Javascript to add to the HTML page. 334 */ 335 protected final String[] getScript() { return ctx.script; } 336 337 /** 338 * CSS style code. 339 * 340 * @see HtmlDocSerializer.Builder#style(String...) 341 * @return 342 * The CSS instructions to add to the HTML page. 343 */ 344 protected final String[] getStyle() { return ctx.style; } 345 346 /** 347 * Stylesheet import URLs. 348 * 349 * @see HtmlDocSerializer.Builder#stylesheet(String...) 350 * @return 351 * The link to the stylesheet of the HTML page. 352 */ 353 protected final String[] getStylesheet() { return ctx.stylesheet; } 354 355 /** 356 * HTML document template. 357 * 358 * @see HtmlDocSerializer.Builder#template(Class) 359 * @return 360 * The template to use for serializing the page. 361 */ 362 protected final HtmlDocTemplate getTemplate() { return ctx.getTemplate(); } 363 364 /** 365 * Prevent word wrap on page. 366 * 367 * @see HtmlDocSerializer.Builder#nowrap() 368 * @return 369 * <jk>true</jk> if <js>"* {white-space:nowrap}"</js> should be added to the CSS instructions on the page to prevent word wrapping. 370 */ 371 protected final boolean isNowrap() { return ctx.nowrap; } 372 373 /** 374 * Resolve $ variables in serialized POJO. 375 * 376 * @see HtmlDocSerializer.Builder#resolveBodyVars() 377 * @return 378 * <jk>true</jk> if $ variables in serialized POJO should be resolved. 379 */ 380 protected final boolean isResolveBodyVars() { return ctx.resolveBodyVars; } 381 382 @Override /* Overridden from HtmlStrippedDocSerializerSession */ 383 protected FluentMap<String,Object> properties() { 384 return super.properties() 385 .a("ctx", ctx) 386 .a("varResolver", getVarResolver()); 387 } 388}