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.html.HtmlDocSerializer.*;
016
017import java.io.IOException;
018import java.util.*;
019
020import org.apache.juneau.*;
021import org.apache.juneau.collections.*;
022import org.apache.juneau.serializer.*;
023import org.apache.juneau.svl.*;
024
025/**
026 * Context object that lives for the duration of a single serialization of {@link HtmlSerializer} and its subclasses.
027 *
028 * <p>
029 * See {@link Serializer} for details.
030 *
031 * <p>
032 * This class is NOT thread safe.  It is meant to be discarded after one-time use.
033 */
034public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession {
035
036   private static final VarResolver DEFAULT_VR = VarResolver.create().defaultVars().vars(HtmlWidgetVar.class).build();
037
038   private final HtmlDocSerializer ctx;
039   private final String[] navlinks, head, header, nav, aside, footer;
040   private final AsideFloat asideFloat;
041   private final Set<String> style, stylesheet, script;
042   private final boolean nowrap;
043
044   /**
045    * Create a new session using properties specified in the context.
046    *
047    * @param ctx
048    *    The context creating this session object.
049    *    The context contains all the configuration settings for this object.
050    * @param args
051    *    Runtime arguments.
052    */
053   protected HtmlDocSerializerSession(HtmlDocSerializer ctx, SerializerSessionArgs args) {
054      super(ctx, args);
055      this.ctx = ctx;
056
057      header = getProperty(HTMLDOC_header, String[].class, ctx.getHeader());
058      nav = getProperty(HTMLDOC_nav, String[].class, ctx.getNav());
059      aside = getProperty(HTMLDOC_aside, String[].class, ctx.getAside());
060      asideFloat = getProperty(HTMLDOC_asideFloat, AsideFloat.class, ctx.getAsideFloat());
061      footer = getProperty(HTMLDOC_footer, String[].class, ctx.getFooter());
062      navlinks = getProperty(HTMLDOC_navlinks, String[].class, ctx.getNavlinks());
063
064      // These can contain dups after variable resolution, so de-dup them with hashsets.
065      style = ASet.of(getProperty(HTMLDOC_style, String[].class, ctx.getStyle()));
066      stylesheet = ASet.of(getProperty(HTMLDOC_stylesheet, String[].class, ctx.getStylesheet()));
067      script = ASet.of(getProperty(HTMLDOC_script, String[].class, ctx.getScript()));
068
069      head = getProperty(HTMLDOC_head, String[].class, ctx.getHead());
070      nowrap = getProperty(HTMLDOC_nowrap, boolean.class, ctx.isNowrap());
071
072      varSessionObject(HtmlWidgetVar.SESSION_htmlWidgets, ctx.getWidgets());
073   }
074
075   @Override /* SerializerSession */
076   protected VarResolverSession createDefaultVarResolverSession() {
077      return DEFAULT_VR.createSession();
078   }
079
080   /**
081    * Returns the {@link HtmlDocSerializer#HTMLDOC_navlinks} setting value in this context.
082    *
083    * @return
084    *    The {@link HtmlDocSerializer#HTMLDOC_navlinks} setting value in this context.
085    *    <jk>null</jk> if not specified.
086    *    Never an empty map.
087    */
088   public final String[] getNavLinks() {
089      return navlinks;
090   }
091
092   @Override /* Serializer */
093   protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException {
094
095      try (HtmlWriter w = getHtmlWriter(out)) {
096         try {
097            getTemplate().writeTo(this, w, o);
098         } catch (Exception e) {
099            throw new SerializeException(e);
100         }
101      }
102   }
103
104   /**
105    * Calls the parent {@link #doSerialize(SerializerPipe, Object)} method which invokes just the HTML serializer.
106    *
107    * @param out
108    *    Where to send the output from the serializer.
109    * @param o The object being serialized.
110    * @throws Exception Error occurred during serialization.
111    */
112   public void parentSerialize(Object out, Object o) throws Exception {
113      try (SerializerPipe pipe = createPipe(out)) {
114         super.doSerialize(pipe, o);
115      }
116   }
117   //-----------------------------------------------------------------------------------------------------------------
118   // Properties
119   //-----------------------------------------------------------------------------------------------------------------
120
121   /**
122    * Configuration property:  Aside section contents.
123    *
124    * @see HtmlDocSerializer#HTMLDOC_aside
125    * @return
126    *    The overridden contents of the aside section on the HTML page.
127    */
128   protected final String[] getAside() {
129      return aside;
130   }
131
132   /**
133    * Configuration property:  Aside section contents float.
134    *
135    * @see HtmlDocSerializer#HTMLDOC_asideFloat
136    * @return
137    *    The location of where to place the aside section.
138    */
139   protected final AsideFloat getAsideFloat() {
140      return asideFloat;
141   }
142
143   /**
144    * Configuration property:  Footer section contents.
145    *
146    * @see HtmlDocSerializer#HTMLDOC_footer
147    * @return
148    *    The overridden contents of the footer section on the HTML page.
149    */
150   protected final String[] getFooter() {
151      return footer;
152   }
153
154   /**
155    * Configuration property:  Additional head section content.
156    *
157    * @see HtmlDocSerializer#HTMLDOC_head
158    * @return
159    *    HTML content to add to the head section of the HTML page.
160    */
161   protected final String[] getHead() {
162      return head;
163   }
164
165   /**
166    * Configuration property:  Header section contents.
167    *
168    * @see HtmlDocSerializer#HTMLDOC_header
169    * @return
170    *    The overridden contents of the header section on the HTML page.
171    */
172   protected final String[] getHeader() {
173      return header;
174   }
175
176   /**
177    * Configuration property:  Nav section contents.
178    *
179    * @see HtmlDocSerializer#HTMLDOC_nav
180    * @return
181    *    The overridden contents of the nav section on the HTML page.
182    */
183   protected final String[] getNav() {
184      return nav;
185   }
186
187   /**
188    * Configuration property:  Page navigation links.
189    *
190    * @see HtmlDocSerializer#HTMLDOC_navlinks
191    * @return
192    *    Navigation links to add to the HTML page.
193    */
194   protected final String[] getNavlinks() {
195      return navlinks;
196   }
197
198   /**
199    * Configuration property:  No-results message.
200    *
201    * @see HtmlDocSerializer#HTMLDOC_noResultsMessage
202    * @return
203    *    The message used when serializing an empty array or empty list.
204    */
205   protected final String getNoResultsMessage() {
206      return ctx.getNoResultsMessage();
207   }
208
209   /**
210    * Configuration property:  Prevent word wrap on page.
211    *
212    * @see HtmlDocSerializer#HTMLDOC_nowrap
213    * @return
214    *    <jk>true</jk> if <js>"* {white-space:nowrap}"</js> shoudl be added to the CSS instructions on the page to prevent word wrapping.
215    */
216   protected final boolean isNowrap() {
217      return nowrap;
218   }
219
220   /**
221    * Configuration property:  Javascript code.
222    *
223    * @see HtmlDocSerializer#HTMLDOC_script
224    * @return
225    *    Arbitrary Javascript to add to the HTML page.
226    */
227   protected final Set<String> getScript() {
228      return script;
229   }
230
231   /**
232    * Configuration property:  CSS style code.
233    *
234    * @see HtmlDocSerializer#HTMLDOC_style
235    * @return
236    *    The CSS instructions to add to the HTML page.
237    */
238   protected final Set<String> getStyle() {
239      return style;
240   }
241
242   /**
243    * Configuration property:  Stylesheet import URLs.
244    *
245    * @see HtmlDocSerializer#HTMLDOC_stylesheet
246    * @return
247    *    The link to the stylesheet of the HTML page.
248    */
249   protected final Set<String> getStylesheet() {
250      return stylesheet;
251   }
252
253   /**
254    * Configuration property:  HTML document template.
255    *
256    * @see HtmlDocSerializer#HTMLDOC_template
257    * @return
258    *    The template to use for serializing the page.
259    */
260   protected final HtmlDocTemplate getTemplate() {
261      return ctx.getTemplate();
262   }
263
264   /**
265    * Configuration property:  Page navigation links.
266    *
267    * @see HtmlDocSerializer#HTMLDOC_navlinks
268    * @return
269    *    Navigation links to add to the HTML page.
270    */
271   protected final Collection<HtmlWidget> getWidgets() {
272      return ctx.getWidgets().values();
273   }
274
275   //-----------------------------------------------------------------------------------------------------------------
276   // Other methods
277   //-----------------------------------------------------------------------------------------------------------------
278
279   @Override /* Session */
280   public OMap toMap() {
281      return super.toMap()
282         .a("HtmlDocSerializerSession", new DefaultFilteringOMap()
283            .a("aside", aside)
284            .a("head", head)
285            .a("header", header)
286            .a("footer", footer)
287            .a("nav", nav)
288            .a("navlinks", navlinks)
289            .a("script", script)
290            .a("style", style)
291            .a("stylesheet", stylesheet)
292            .a("varResolver", getVarResolver())
293         );
294   }
295}