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  
23  import java.util.List;
24  
25  import com.google.common.base.Joiner;
26  import com.google.common.base.Strings;
27  import com.google.common.collect.FluentIterable;
28  import com.google.common.collect.Lists;
29  import org.devacfr.maven.skins.reflow.HtmlTool;
30  import org.devacfr.maven.skins.reflow.ISkinConfig;
31  
32  import static com.google.common.collect.FluentIterable.concat;
33  import static java.util.Objects.requireNonNull;
34  
35  /**
36   * The abstract class of all component used in Reflow rendering.
37   *
38   * @author devacfr
39   * @since 2.0
40   */
41  public abstract class Component {
42  
43      /** */
44      private String cssClass;
45  
46      /** */
47      private final List<String> cssOptions = Lists.newArrayList();
48  
49      /** */
50      private final List<Component> children = Lists.newArrayList();
51  
52      /**
53       * @return Returns a {@link String} representing the css classes to apply to component.
54       */
55      @Nonnull
56      public String getCssClass() {
57          if (Strings.isNullOrEmpty(cssClass)) {
58              return "";
59          }
60          return cssClass;
61      }
62  
63      /**
64       * @param cssClass
65       *            the cssClass to set
66       */
67      protected void setCssClass(final String cssClass) {
68          this.cssClass = cssClass;
69      }
70  
71      /**
72       * Gets the css options associated to component. A css option is css class that can be set directly on the component
73       * or on {@code <body>} element as global state.
74       * <p>
75       * Used generally in association with javascript to adapt specific javascript action to current state of component.
76       * </p>
77       *
78       * @return Returns a {@link String} representing the css options associated to component.
79       */
80      @Nonnull
81      public final String getCssOptions() {
82          return concat(this.cssOptions,
83              concat(FluentIterable.from(children).transform(component -> component.cssOptions))).join(Joiner.on(' '));
84      }
85  
86      /**
87       * Add components to this component.
88       *
89       * @param components
90       *            list of component
91       */
92      protected void addChildren(final Component... components) {
93          this.children.addAll(Lists.newArrayList(components));
94      }
95  
96      /**
97       * Add cssOption to this component.
98       *
99       * @param cssOptions
100      *            a css option.
101      */
102     protected final void addCssOptions(@Nonnull final String... cssOptions) {
103         this.cssOptions.addAll(Lists.newArrayList(cssOptions));
104     }
105 
106     /**
107      * generic pre-rendering method executed on all components of context.
108      *
109      * @param skinConfig
110      *            the current skin config.
111      * @param bodyContent
112      *            the current body content.
113      * @return Returns a {@code String} representing the transformed body content on pre-rendering.
114      */
115     protected String onPreRender(@Nonnull final ISkinConfig skinConfig, @Nonnull final String bodyContent) {
116         final StringBuilder str = new StringBuilder(bodyContent);
117         this.children.forEach(component -> {
118             final String content = str.toString();
119             str.setLength(0);
120             str.append(component.onPreRender(skinConfig, content));
121         });
122         return str.toString();
123     }
124 
125     /**
126      * Gets the tool {@link HtmlTool}.
127      *
128      * @param skinConfig
129      *            a config (can <b>not</b> be {@code null}).
130      * @return Returns the tool {@link HtmlTool}.
131      * @since 2.1
132      */
133     protected HtmlTool getHtmlTool(@Nonnull final ISkinConfig skinConfig) {
134         return requireNonNull(skinConfig).getToolbox("htmlTool", HtmlTool.class);
135     }
136 
137     /**
138      * @param skinConfig
139      *            a config (can <b>not</b> be {@code null}).
140      * @return Returns the html body content stored in velocity context.
141      * @since 2.1
142      */
143     @Nonnull
144     protected String getBodyContent(@Nonnull final ISkinConfig skinConfig) {
145         return requireNonNull(skinConfig).getContextValue("bodyContent", String.class);
146     }
147 }