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 static org.apache.juneau.collections.JsonMap.*;
016
017import java.io.IOException;
018import java.lang.reflect.*;
019import java.nio.charset.*;
020import java.util.*;
021import java.util.function.*;
022
023import org.apache.juneau.*;
024import org.apache.juneau.collections.*;
025import org.apache.juneau.httppart.*;
026import org.apache.juneau.internal.*;
027import org.apache.juneau.serializer.*;
028import org.apache.juneau.svl.*;
029
030/**
031 * Context object that lives for the duration of a single serialization of {@link HtmlSerializer} and its subclasses.
032 *
033 * <p>
034 * See {@link Serializer} for details.
035 *
036 * <h5 class='section'>Notes:</h5><ul>
037 *    <li class='warn'>This class is not thread safe and is typically discarded after one use.
038 * </ul>
039 *
040 * <h5 class='section'>See Also:</h5><ul>
041 *    <li class='link'><a class="doclink" href="../../../../index.html#jm.HtmlDetails">HTML Details</a>
042
043 * </ul>
044 */
045public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession {
046
047   //-----------------------------------------------------------------------------------------------------------------
048   // Static
049   //-----------------------------------------------------------------------------------------------------------------
050
051   private static final VarResolver DEFAULT_VR = VarResolver.create().defaultVars().vars(HtmlWidgetVar.class).build();
052
053   /**
054    * Creates a new builder for this object.
055    *
056    * @param ctx The context creating this session.
057    * @return A new builder.
058    */
059   public static Builder create(HtmlDocSerializer ctx) {
060      return new Builder(ctx);
061   }
062
063   //-----------------------------------------------------------------------------------------------------------------
064   // Builder
065   //-----------------------------------------------------------------------------------------------------------------
066
067   /**
068    * Builder class.
069    */
070   @FluentSetters
071   public static class Builder extends HtmlStrippedDocSerializerSession.Builder {
072
073      HtmlDocSerializer ctx;
074
075      /**
076       * Constructor
077       *
078       * @param ctx The context creating this session.
079       */
080      protected Builder(HtmlDocSerializer ctx) {
081         super(ctx);
082         this.ctx = ctx;
083      }
084
085      @Override
086      public HtmlDocSerializerSession build() {
087         return new HtmlDocSerializerSession(this);
088      }
089
090      // <FluentSetters>
091
092      @Override /* GENERATED - org.apache.juneau.ContextSession.Builder */
093      public <T> Builder apply(Class<T> type, Consumer<T> apply) {
094         super.apply(type, apply);
095         return this;
096      }
097
098      @Override /* GENERATED - org.apache.juneau.ContextSession.Builder */
099      public Builder debug(Boolean value) {
100         super.debug(value);
101         return this;
102      }
103
104      @Override /* GENERATED - org.apache.juneau.ContextSession.Builder */
105      public Builder properties(Map<String,Object> value) {
106         super.properties(value);
107         return this;
108      }
109
110      @Override /* GENERATED - org.apache.juneau.ContextSession.Builder */
111      public Builder property(String key, Object value) {
112         super.property(key, value);
113         return this;
114      }
115
116      @Override /* GENERATED - org.apache.juneau.ContextSession.Builder */
117      public Builder unmodifiable() {
118         super.unmodifiable();
119         return this;
120      }
121
122      @Override /* GENERATED - org.apache.juneau.BeanSession.Builder */
123      public Builder locale(Locale value) {
124         super.locale(value);
125         return this;
126      }
127
128      @Override /* GENERATED - org.apache.juneau.BeanSession.Builder */
129      public Builder localeDefault(Locale value) {
130         super.localeDefault(value);
131         return this;
132      }
133
134      @Override /* GENERATED - org.apache.juneau.BeanSession.Builder */
135      public Builder mediaType(MediaType value) {
136         super.mediaType(value);
137         return this;
138      }
139
140      @Override /* GENERATED - org.apache.juneau.BeanSession.Builder */
141      public Builder mediaTypeDefault(MediaType value) {
142         super.mediaTypeDefault(value);
143         return this;
144      }
145
146      @Override /* GENERATED - org.apache.juneau.BeanSession.Builder */
147      public Builder timeZone(TimeZone value) {
148         super.timeZone(value);
149         return this;
150      }
151
152      @Override /* GENERATED - org.apache.juneau.BeanSession.Builder */
153      public Builder timeZoneDefault(TimeZone value) {
154         super.timeZoneDefault(value);
155         return this;
156      }
157
158      @Override /* GENERATED - org.apache.juneau.serializer.SerializerSession.Builder */
159      public Builder javaMethod(Method value) {
160         super.javaMethod(value);
161         return this;
162      }
163
164      @Override /* GENERATED - org.apache.juneau.serializer.SerializerSession.Builder */
165      public Builder resolver(VarResolverSession value) {
166         super.resolver(value);
167         return this;
168      }
169
170      @Override /* GENERATED - org.apache.juneau.serializer.SerializerSession.Builder */
171      public Builder schema(HttpPartSchema value) {
172         super.schema(value);
173         return this;
174      }
175
176      @Override /* GENERATED - org.apache.juneau.serializer.SerializerSession.Builder */
177      public Builder schemaDefault(HttpPartSchema value) {
178         super.schemaDefault(value);
179         return this;
180      }
181
182      @Override /* GENERATED - org.apache.juneau.serializer.SerializerSession.Builder */
183      public Builder uriContext(UriContext value) {
184         super.uriContext(value);
185         return this;
186      }
187
188      @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializerSession.Builder */
189      public Builder fileCharset(Charset value) {
190         super.fileCharset(value);
191         return this;
192      }
193
194      @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializerSession.Builder */
195      public Builder streamCharset(Charset value) {
196         super.streamCharset(value);
197         return this;
198      }
199
200      @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializerSession.Builder */
201      public Builder useWhitespace(Boolean value) {
202         super.useWhitespace(value);
203         return this;
204      }
205
206      // </FluentSetters>
207   }
208
209   //-----------------------------------------------------------------------------------------------------------------
210   // Instance
211   //-----------------------------------------------------------------------------------------------------------------
212
213   /**
214    * Constructor.
215    *
216    * @param builder The builder for this object.
217    */
218   protected HtmlDocSerializerSession(Builder builder) {
219      super(builder);
220      ctx = builder.ctx;
221      addVarBean(HtmlWidgetMap.class, ctx.getWidgets());
222   }
223
224   private final HtmlDocSerializer ctx;
225
226   @Override /* SerializerSession */
227   protected VarResolverSession createDefaultVarResolverSession() {
228      return DEFAULT_VR.createSession();
229   }
230
231   /**
232    * Returns the {@link HtmlDocSerializer.Builder#navlinks(String...)} setting value in this context.
233    *
234    * @return
235    *    The {@link HtmlDocSerializer.Builder#navlinks(String...)} setting value in this context.
236    *    <jk>null</jk> if not specified.
237    *    Never an empty map.
238    */
239   public final String[] getNavLinks() {
240      return ctx.navlinks;
241   }
242
243   @Override /* Serializer */
244   protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException {
245
246      try (HtmlWriter w = getHtmlWriter(out)) {
247         try {
248            getTemplate().writeTo(this, w, o);
249         } catch (Exception e) {
250            throw new SerializeException(e);
251         }
252      }
253   }
254
255   /**
256    * Calls the parent {@link #doSerialize(SerializerPipe, Object)} method which invokes just the HTML serializer.
257    *
258    * @param out
259    *    Where to send the output from the serializer.
260    * @param o The object being serialized.
261    * @throws Exception Error occurred during serialization.
262    */
263   public void parentSerialize(Object out, Object o) throws Exception {
264      try (SerializerPipe pipe = createPipe(out)) {
265         super.doSerialize(pipe, o);
266      }
267   }
268   //-----------------------------------------------------------------------------------------------------------------
269   // Properties
270   //-----------------------------------------------------------------------------------------------------------------
271
272   /**
273    * Aside section contents.
274    *
275    * @see HtmlDocSerializer.Builder#aside(String...)
276    * @return
277    *    The overridden contents of the aside section on the HTML page.
278    */
279   protected final String[] getAside() {
280      return ctx.aside;
281   }
282
283   /**
284    * Aside section contents float.
285    *
286    * @see HtmlDocSerializer.Builder#asideFloat(AsideFloat)
287    * @return
288    *    The location of where to place the aside section.
289    */
290   protected final AsideFloat getAsideFloat() {
291      return ctx.asideFloat;
292   }
293
294   /**
295    * Footer section contents.
296    *
297    * @see HtmlDocSerializer.Builder#footer(String...)
298    * @return
299    *    The overridden contents of the footer section on the HTML page.
300    */
301   protected final String[] getFooter() {
302      return ctx.footer;
303   }
304
305   /**
306    * Additional head section content.
307    *
308    * @see HtmlDocSerializer.Builder#head(String...)
309    * @return
310    *    HTML content to add to the head section of the HTML page.
311    */
312   protected final String[] getHead() {
313      return ctx.head;
314   }
315
316   /**
317    * Header section contents.
318    *
319    * @see HtmlDocSerializer.Builder#header(String...)
320    * @return
321    *    The overridden contents of the header section on the HTML page.
322    */
323   protected final String[] getHeader() {
324      return ctx.header;
325   }
326
327   /**
328    * Nav section contents.
329    *
330    * @see HtmlDocSerializer.Builder#nav(String...)
331    * @return
332    *    The overridden contents of the nav section on the HTML page.
333    */
334   protected final String[] getNav() {
335      return ctx.nav;
336   }
337
338   /**
339    * Page navigation links.
340    *
341    * @see HtmlDocSerializer.Builder#navlinks(String...)
342    * @return
343    *    Navigation links to add to the HTML page.
344    */
345   protected final String[] getNavlinks() {
346      return ctx.navlinks;
347   }
348
349   /**
350    * No-results message.
351    *
352    * @see HtmlDocSerializer.Builder#noResultsMessage(String)
353    * @return
354    *    The message used when serializing an empty array or empty list.
355    */
356   protected final String getNoResultsMessage() {
357      return ctx.getNoResultsMessage();
358   }
359
360   /**
361    * Prevent word wrap on page.
362    *
363    * @see HtmlDocSerializer.Builder#nowrap()
364    * @return
365    *    <jk>true</jk> if <js>"* {white-space:nowrap}"</js> should be added to the CSS instructions on the page to prevent word wrapping.
366    */
367   protected final boolean isNowrap() {
368      return ctx.nowrap;
369   }
370
371   /**
372    * Resolve $ variables in serialized POJO.
373    *
374    * @see HtmlDocSerializer.Builder#resolveBodyVars()
375    * @return
376    *    <jk>true</jk> if $ variables in serialized POJO should be resolved.
377    */
378   protected final boolean isResolveBodyVars() {
379      return ctx.resolveBodyVars;
380   }
381
382   /**
383    * Javascript code.
384    *
385    * @see HtmlDocSerializer.Builder#script(String...)
386    * @return
387    *    Arbitrary Javascript to add to the HTML page.
388    */
389   protected final String[] getScript() {
390      return ctx.script;
391   }
392
393   /**
394    * CSS style code.
395    *
396    * @see HtmlDocSerializer.Builder#style(String...)
397    * @return
398    *    The CSS instructions to add to the HTML page.
399    */
400   protected final String[] getStyle() {
401      return ctx.style;
402   }
403
404   /**
405    * Stylesheet import URLs.
406    *
407    * @see HtmlDocSerializer.Builder#stylesheet(String...)
408    * @return
409    *    The link to the stylesheet of the HTML page.
410    */
411   protected final String[] getStylesheet() {
412      return ctx.stylesheet;
413   }
414
415   /**
416    * HTML document template.
417    *
418    * @see HtmlDocSerializer.Builder#template(Class)
419    * @return
420    *    The template to use for serializing the page.
421    */
422   protected final HtmlDocTemplate getTemplate() {
423      return ctx.getTemplate();
424   }
425
426   /**
427    * Performs an action on all widgets defined in his session.
428    *
429    * @param action The action to perform.
430    * @see HtmlDocSerializer.Builder#widgets(Class...)
431    * @return This object.
432    */
433   protected final HtmlDocSerializerSession forEachWidget(Consumer<HtmlWidget> action) {
434      ctx.forEachWidget(action);
435      return this;
436   }
437
438   //-----------------------------------------------------------------------------------------------------------------
439   // Other methods
440   //-----------------------------------------------------------------------------------------------------------------
441
442   @Override /* ContextSession */
443   protected JsonMap properties() {
444      return filteredMap("ctx", ctx, "varResolver", getVarResolver());
445   }
446}