View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.devacfr.maven.skins.reflow.model;
20  
21  import javax.annotation.Nonnull;
22  import javax.annotation.Nullable;
23  
24  import java.util.List;
25  import java.util.Set;
26  
27  import com.google.common.collect.Sets;
28  import org.apache.commons.lang3.builder.ToStringBuilder;
29  import org.devacfr.maven.skins.reflow.HtmlTool;
30  import org.devacfr.maven.skins.reflow.HtmlTool.IdElement;
31  import org.devacfr.maven.skins.reflow.ISkinConfig;
32  import org.devacfr.maven.skins.reflow.Xpp3Utils;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  /**
37   * Represents the base of Table of content component.
38   *
39   * @author devacfr
40   * @since 2.0
41   * @param <T>
42   *            the type of inherit of {@link Toc}.
43   */
44  public abstract class Toc<T extends Toc<?>> extends BsComponent {
45  
46      private static final Set<String> TOC_TYPES = Sets.newHashSet("sidebar", "top", "false");
47  
48      /** */
49      public static final String COMPONENT = "toc";
50  
51      /** */
52      private static final Logger LOGGER = LoggerFactory.getLogger(Toc.class);
53  
54      /** enable by default */
55      private boolean enabled = true;
56  
57      /** */
58      private final String type;
59  
60      /**
61       * @param config
62       *            a config (can <b>not</b> be {@code null}).
63       * @param preferredType
64       *            the default type of Toc to use.
65       * @return Returns new instance corresponding {@link Toc} to configuration.
66       */
67      public static Toc<?> createToc(@Nonnull final ISkinConfig config, @Nullable final String preferredType) {
68          Toc<?> toc = null;
69          String type = config.getPropertyValue(COMPONENT, String.class, preferredType);
70          if (LOGGER.isTraceEnabled()) {
71              LOGGER.trace("Page '{}' Find Toc: {}", config.getFileId(), type);
72          }
73          if (!TOC_TYPES.contains(type)) {
74              type = preferredType;
75          }
76          if (type == null) {
77              type = "";
78          }
79          switch (type) {
80              case "sidebar":
81                  toc = createSidebar(config);
82                  break;
83              case "top":
84                  toc = createTopBar(config);
85                  break;
86              default:
87                  // create a disabled empty toc
88                  toc = new Toc<Toc<?>>("", "") {};
89  
90                  toc.withEnabled(false);
91                  break;
92          }
93  
94          return toc;
95      }
96  
97      /**
98       * @param config
99       *            a config (can <b>not</b> be {@code null}).
100      * @return Returns new instance of Toc sidebar.
101      */
102     public static Toc<?> createSidebar(@Nonnull final ISkinConfig config) {
103         return new TocSidebar(config);
104     }
105 
106     /**
107      * @param config
108      *            a config (can <b>not</b> be {@code null}).
109      * @return Returns new instance Toc top bar.
110      */
111     public static Toc<?> createTopBar(@Nonnull final ISkinConfig config) {
112         return new TocTopBar(config);
113     }
114 
115     /**
116      * @param type
117      *            the {@link String} representation of Toc.
118      * @param component
119      *            the bootstrap component name.
120      */
121     protected Toc(final String type, final String component) {
122         super(component);
123         this.type = type;
124     }
125 
126     /**
127      * @return Returns the fluent instance.
128      */
129     @SuppressWarnings("unchecked")
130     protected T self() {
131         return (T) this;
132     }
133 
134     /**
135      * @return Returns the {@link String} reprensenting the type of {@link Toc}.
136      */
137     public String getType() {
138         return type;
139     }
140 
141     /**
142      * Gets the indicating whether is enable.
143      *
144      * @return Returns {@code true} if is enable, otherwise {@code false}.
145      */
146     public boolean isEnabled() {
147         return enabled;
148     }
149 
150     /**
151      * @param skinConfig
152      *            a config (can <b>not</b> be {@code null}).
153      * @return Returns a list of {@link IdElement} representing the heading tree containing in current page.
154      * @since 2.1
155      */
156     public List<? extends IdElement> getTocItems(final ISkinConfig skinConfig) {
157         final HtmlTool htmlTool = getHtmlTool(skinConfig);
158         final String bodyContent = getBodyContent(skinConfig);
159 
160         final List<? extends IdElement> tocItems = htmlTool.headingTree(bodyContent,
161             Xpp3Utils.getChildren(skinConfig.get("sections")));
162         return tocItems;
163     }
164 
165     /**
166      * Sets the indicating whether is enable.
167      *
168      * @param enabled
169      *            status to use.
170      * @return Returns the fluent instance.
171      */
172     protected T withEnabled(final boolean enabled) {
173         this.enabled = enabled;
174         return self();
175     }
176 
177     @Override
178     protected String onPreRender(final @Nonnull ISkinConfig skinConfig, final @Nonnull String bodyContent) {
179         if (this.enabled) {
180             final HtmlTool htmlTool = getHtmlTool(skinConfig);
181             return htmlTool.ensureHeadingIds(skinConfig.getContext().getType(),
182                 skinConfig.getFileId(),
183                 bodyContent,
184                 HtmlTool.DEFAULT_SLUG_SEPARATOR);
185         }
186         return bodyContent;
187     }
188 
189     /**
190      * {@inheritDoc}
191      */
192     @Override
193     public String toString() {
194         return ToStringBuilder.reflectionToString(this);
195     }
196 }