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