1. Project Clover database mar. janv. 20 2026 12:32:22 CET
  2. Package org.devacfr.maven.skins.reflow.context

File Context.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

18
63
12
1
273
146
25
0,4
5,25
12
2,08

Classes

Class Line # Actions
Context 47 63 0% 25 8
0.913978591,4%
 

Contributing tests

This file is covered by 30 tests. .

Source view

1    /*
2    * Copyright 2012-2025 Christophe Friederich
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10    * Unless required by applicable law or agreed to in writing, software
11    * distributed under the License is distributed on an "AS IS" BASIS,
12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    * See the License for the specific language governing permissions and
14    * limitations under the License.
15    */
16    package org.devacfr.maven.skins.reflow.context;
17   
18    import static java.util.Objects.requireNonNull;
19   
20    import com.google.common.collect.ImmutableMap;
21    import com.google.common.collect.Lists;
22    import java.util.List;
23    import java.util.Map;
24    import java.util.Optional;
25    import javax.annotation.Nonnull;
26    import org.apache.commons.lang3.builder.ToStringBuilder;
27    import org.codehaus.plexus.util.xml.Xpp3Dom;
28    import org.devacfr.maven.skins.reflow.HtmlTool;
29    import org.devacfr.maven.skins.reflow.ISkinConfig;
30    import org.devacfr.maven.skins.reflow.model.Component;
31    import org.devacfr.maven.skins.reflow.model.Footer;
32    import org.devacfr.maven.skins.reflow.model.NavSideMenu;
33    import org.devacfr.maven.skins.reflow.model.Navbar;
34    import org.devacfr.maven.skins.reflow.model.ScrollTop;
35    import org.devacfr.maven.skins.reflow.model.SideNavMenuItem;
36    import org.slf4j.Logger;
37    import org.slf4j.LoggerFactory;
38   
39    /**
40    * The base class of all contexts depending type of page.
41    *
42    * @author Christophe Friederich
43    * @since 2.0
44    * @param <T>
45    * type of inherrit context object.
46    */
 
47    public abstract class Context<T extends Context<?>> extends Component {
48   
49    /**
50    * map containing the equivalence of font awesome characters with image found in report pages.
51    */
52    private static final Map<String, String> ICON_REPLACEMENTS = ImmutableMap.<String, String> builder()
53    .put("img[src$=images/add.gif]", "<i class=\"fas fa-plus\"></i>")
54    .put("img[src$=images/remove.gif]", "<i class=\"fas fa-minus\"></i>")
55    .put("img[src$=images/fix.gif]", "<i class=\"fas fa-wrench\"></i>")
56    .put("img[src$=images/update.gif]", "<i class=\"fas fa-redo\"></i>")
57    .put("img[src$=images/icon_help_sml.gif]", "<i class=\"fas fa-question\"></i>")
58    .put("img[src$=images/icon_success_sml.gif]", "<i class=\"fas fa-check-circle\"></i>")
59    .put("img[src$=images/icon_warning_sml.gif]", "<i class=\"fas fa-exclamation-triangle\"></i>")
60    .put("img[src$=images/icon_error_sml.gif]", "<i class=\"fas fa-exclamation-circle\"></i>")
61    .put("img[src$=images/icon_info_sml.gif]", "<i class=\"fas fa-info\"></i>")
62    .build();
63   
64    /** */
65    private static final Logger LOGGER = LoggerFactory.getLogger(Context.class);
66   
67    /** */
68    private ContextType type;
69   
70    /** */
71    private final Navbar navbar;
72   
73    /** */
74    private final Footer footer;
75   
76    /** */
77    private final ScrollTop scrollTop;
78   
79    /**
80    * Build a context depending of current type of page.
81    *
82    * @param config
83    * a config (can not be {@code null}).
84    * @return Returns a new instance of {@link Context} depending of current page.
85    */
 
86  22 toggle @Nonnull
87    public static Context<?> buildContext(@Nonnull final ISkinConfig config) {
88  22 requireNonNull(config);
89  22 final String fileId = requireNonNull(config.getFileId());
90   
91  22 ContextType type = ContextType.page;
92  22 final List<SideNavMenuItem> allSideNaveMenuItems = NavSideMenu.findAllSideNavMenuItems(config);
93  22 if (LOGGER.isTraceEnabled()) {
94  0 LOGGER.trace("findAllSideNavMenuItems: " + allSideNaveMenuItems);
95    }
96  22 final Xpp3Dom pageProperties = config.getPageProperties();
97   
98  22 if (pageProperties != null) {
99  15 if (pageProperties.getAttribute("type") != null) {
100  3 type = ContextType.valueOf(pageProperties.getAttribute("type"));
101    }
102   
103    // frame type whether page associates to document page
104  15 if (allSideNaveMenuItems.stream().filter(item -> fileId.equals(item.getSlugName())).count() > 0) {
105  1 type = ContextType.frame;
106    }
107    }
108    // if (type== null) {
109    // type = ContextType.page;
110    // }
111  22 Context<?> context = null;
112  22 switch (type) {
113  1 case doc:
114  1 context = new DocumentContext(config);
115  1 break;
116   
117  1 case frame:
118    // search the parent document page
119  1 final Optional<SideNavMenuItem> menuItem = allSideNaveMenuItems.stream()
120    .filter(item -> fileId.equals(item.getSlugName()))
121    .findFirst();
122  1 final SideNavMenuItem item = menuItem.get();
123  1 final String documentParent = item.getParent();
124  1 context = new FrameContext(config, documentParent);
125  1 break;
126  2 case body:
127  2 context = new BodyContext(config);
128  2 break;
129  18 case page:
130  0 default:
131  18 context = new PageContext(config);
132  18 break;
133    }
134  22 return context;
135    }
136   
137    /**
138    * Default constructor.
139    *
140    * @param config
141    * a config (can not be {@code null}).
142    * @param type
143    * the type of context (can not be {@code null}).
144    */
 
145  30 toggle public Context(@Nonnull final ISkinConfig config, @Nonnull final ContextType type) {
146  30 super(config);
147  30 this.withType(requireNonNull(type));
148  30 this.navbar = new Navbar(config);
149  30 this.scrollTop = new ScrollTop(config);
150  30 this.footer = new Footer(config);
151   
152  30 this.initialize();
153   
154    // the ordering is important for execute preRender method
155  30 this.addChildren(this.navbar, this.scrollTop, this.footer);
156    }
157   
158    /**
159    * Allows to initialize the context.
160    */
 
161  28 toggle protected void initialize() {
162    // enable AnchorJS
163  28 if (!config.not("anchorJS")) {
164  28 this.addCssOptions("anchorjs-enabled");
165    }
166    }
167   
168    /**
169    * Allows to execute action before rendering of component.
170    *
171    * @return Returns the {@link String} representing the transformed body content.
172    * @since 2.1
173    */
 
174  6 toggle public String preRender() {
175  6 return onPreRender(config.getBodyContent());
176    }
177   
 
178  5 toggle @Override
179    protected String onPreRender(final @Nonnull String bodyContent) {
180  5 final HtmlTool htmlTool = config.getHtmlTool();
181  5 String content = bodyContent;
182  5 if (!config.not("imgLightbox")) {
183    // lightbox is enabled by default, so check for false and negate
184  5 content = htmlTool.setAttr(content,
185    "a[href$=jpg], a[href$=JPG], a[href$=jpeg], a[href$=JPEG], "
186    + "a[href$=png], a[href$=gif],a[href$=bmp]:has(img)",
187    "data-lightbox",
188    "page");
189    }
190   
191  5 if (!config.not("html5Anchor")) {
192    // HTML5-style anchors are enabled by default, so check for false and negate
193  5 content = htmlTool.headingAnchorToId(content);
194    }
195   
196  5 if (!config.not("bootstrapCss")) {
197    // Bootstrap CSS class conversion is enabled by default, so check for false and
198    // negate
199  5 content = htmlTool
200    .addClass(content, "table.bodyTable", Lists.newArrayList("table", "table-striped", "table-hover"));
201    // image is responsive by default
202  5 content = htmlTool.addClass(content, "img", Lists.newArrayList("img-fluid"));
203  5 content = htmlTool.fixTableHeads(content);
204    }
205   
206  5 if (!config.not("bootstrapIcons")) {
207    // Bootstrap Icons are enabled by default, so check for false and negate
208  5 content = htmlTool.replaceAll(content, ICON_REPLACEMENTS);
209    }
210   
211    // The <tt> tag is not supported in HTML5 (see
212    // https://www.w3schools.com/tags/tag_tt.asp).
213  5 content = htmlTool.replaceWith(content, "tt", "<code class=\"literal\">");
214  5 return super.onPreRender(content);
215    }
216   
217    /**
218    * @return Returns the {@link Navbar}.
219    */
 
220  3 toggle public Navbar getNavbar() {
221  3 return navbar;
222    }
223   
224    /**
225    * @return Returns the {@link ScrollTop}.
226    */
 
227  3 toggle public ScrollTop getScrollTop() {
228  3 return scrollTop;
229    }
230   
231    /**
232    * @return Returns the {@link Footer}.
233    */
 
234  3 toggle public Footer getFooter() {
235  3 return footer;
236    }
237   
238    /**
239    * Sets the type of context.
240    *
241    * @param type
242    * the of context.
243    * @return Returns the fluent instance context.
244    */
 
245  30 toggle protected T withType(final ContextType type) {
246  30 this.type = type;
247  30 return self();
248    }
249   
250    /**
251    * @return Returns the type of context of page.
252    */
 
253  21 toggle public String getType() {
254  21 return type.name();
255    }
256   
257    /**
258    * @return Returns the fluent instance.
259    */
 
260  30 toggle @SuppressWarnings("unchecked")
261    protected T self() {
262  30 return (T) this;
263    }
264   
265    /**
266    * {@inheritDoc}
267    */
 
268  11 toggle @Override
269    public String toString() {
270  11 return ToStringBuilder.reflectionToString(this);
271    }
272   
273    }