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 }