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.snippet;
20  
21  import javax.annotation.Nonnull;
22  import javax.annotation.Nullable;
23  
24  import org.devacfr.maven.skins.reflow.snippet.ComponentToken.Type;
25  import org.jsoup.Jsoup;
26  import org.jsoup.nodes.Document;
27  import org.jsoup.nodes.Element;
28  
29  import static java.util.Objects.requireNonNull;
30  
31  /**
32   * @author Christophe Friederich
33   * @version 2.4
34   * @param <T>
35   *            type of component
36   */
37  public class SnippetComponent<T extends SnippetComponent<T>> extends Component<T> {
38  
39      /** */
40      private final Type type;
41  
42      @Nonnull
43      public static SnippetComponent<?> createSnippet(@Nonnull final Element element,
44          final Component<?> parent,
45          final Type type) {
46          requireNonNull(element);
47          return new SnippetComponent<>(element, type).addAttributes(element.attributes()).withParent(parent);
48      }
49  
50      /**
51       * @param element
52       * @param type
53       */
54      public SnippetComponent(@Nonnull final Element element, @Nonnull final Type type) {
55          super(element);
56          this.type = requireNonNull(type);
57      }
58  
59      /**
60       * @return
61       */
62      @Nonnull
63      public Type getType() {
64          return type;
65      }
66  
67      @Override
68      protected SnippetComponent<?> getRootParent() {
69          return this;
70      }
71  
72      /**
73       * Render the {@link SnippetComponent} between the {@code startElement} and {@code endElement} include.
74       *
75       * @param context
76       *            the snippet context to use
77       */
78      public void render(final SnippetContext context) {
79          try {
80              final Element element = getElement();
81              final String html = context.renderComponent(this);
82              final Document doc = Jsoup.parse(html);
83              if (doc.body().children().isEmpty()) {
84                  return;
85              }
86              // normally, when debug trace is activated
87              if (doc.body().children().size() > 1) {
88                  final Element div = new Element("div");
89                  doc.body().children().forEach((e) -> div.appendChild(e));
90                  element.replaceWith(div);
91              } else {
92                  final Element el = doc.body().children().first();
93                  // if snippet contains rendered snippet.
94                  if (ComponentResolver.hasIncludedSnippetComponent(el)) {
95                      final SnippetParser parser = context.createChildParser();
96                      final Document childDoc = parser.parse(context.getConfig(), el.outerHtml()).document();
97                      element.replaceWith(childDoc.body().children().first());
98                  } else {
99                      element.replaceWith(el);
100                 }
101             }
102         } catch (final Exception e) {
103             throw new RuntimeException(e.getMessage(), e);
104         }
105     }
106 }