1. Project Clover database mar. janv. 20 2026 12:32:22 CET
  2. Package org.devacfr.maven.skins.reflow.snippet

File Component.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart9.png
22% of files have more coverage

Code metrics

28
63
23
1
286
166
38
0,6
2,74
23
1,65

Classes

Class Line # Actions
Component 44 63 0% 38 21
0.8157894681,6%
 

Contributing tests

This file is covered by 17 tests. .

Source view

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.snippet;
17   
18    import static java.util.Objects.requireNonNull;
19   
20    import com.google.common.base.MoreObjects;
21    import com.google.common.base.Strings;
22    import com.google.common.collect.Maps;
23    import com.google.common.collect.Sets;
24    import java.util.Map;
25    import java.util.Set;
26    import java.util.stream.Collectors;
27    import javax.annotation.Nonnull;
28    import javax.annotation.Nullable;
29    import org.jsoup.nodes.Attribute;
30    import org.jsoup.nodes.Attributes;
31    import org.jsoup.nodes.Element;
32    import org.jsoup.nodes.Node;
33    import org.jsoup.nodes.TextNode;
34    import org.jsoup.parser.Tag;
35   
36    /**
37    * Base of Snippet component.
38    *
39    * @author Christophe Friederich
40    * @version 2.4
41    * @param <T>
42    * type of component
43    */
 
44    public class Component<T extends Component<T>> {
45   
46    private final static Set<String> knownTags = Sets.newHashSet("svg");
47   
48    /** */
49    private final Map<String, String> attributes = Maps.newHashMap();
50   
51    /** */
52    private Component<?> parent;
53   
54    /** */
55    private final Components children = new Components();
56   
57    /** */
58    private final Map<String, Components> childrenMap = Maps.newHashMap();
59   
60    /** */
61    private final Node node;
62   
63    /**
64    * @param node
65    * a node (can <b>not</b> be {@code null}).
66    * @param parent
67    * the parent component
68    * @return the created component
69    */
 
70  317 toggle public static Component<?> createComponent(@Nonnull final Node node, final Component<?> parent) {
71  317 return new Component<>(node).withParent(parent).addAttributes(node.attributes());
72    }
73   
74    /**
75    * @param node
76    * a node (can <b>not</b> be {@code null}).
77    */
 
78  370 toggle protected Component(@Nonnull final Node node) {
79  370 this.node = requireNonNull(node);
80    }
81   
82    /**
83    * @return the name
84    */
 
85  1049 toggle public String getName() {
86  1049 return node.nodeName();
87    }
88   
89    /**
90    * @return
91    */
 
92  577 toggle public boolean isHtmlTag() {
93  577 return node instanceof TextNode || Tag.isKnownTag(node.nodeName()) || knownTags.contains(node.nodeName());
94    }
95   
96    /**
97    * @return the html content
98    */
 
99  321 toggle public String getHtml() {
100  321 if (!isHtmlTag()) {
101  124 if (children.isEmpty()) {
102  12 return "";
103    } else {
104  112 return children.html();
105    }
106    } else {
107  197 return this.node.outerHtml();
108    }
109    }
110   
111    /**
112    * @return
113    */
 
114  15 toggle public String getOwnHtml() {
115  15 if (!isHtmlTag()) {
116  3 return null;
117    } else {
118  12 return this.node.outerHtml();
119    }
120    }
121   
122    /**
123    * @return the parent
124    */
 
125  9 toggle public Component<?> getParent() {
126  9 return parent;
127    }
128   
 
129  52 toggle @Nullable protected Element getElement() {
130  52 if (this.node instanceof Element) {
131  52 return (Element) this.node;
132    }
133  0 return null;
134    }
135   
136    /**
137    * @param name
138    * the name
139    * @return the attribute or child component value
140    */
 
141  307 toggle public Object get(@Nonnull final String name) {
142  307 requireNonNull(name);
143  307 String key = name.toLowerCase();
144    // if attribute
145  307 if (this.attributes.containsKey(key)) {
146  98 return this.attributes.get(key);
147    } else {
148    // is children component?
149    // check if 's' suffix allowing to retrieve children component as list
150  209 if (key.endsWith("s") && !this.childrenMap.containsKey(key)) {
151  9 key = key.substring(0, key.length() - 1);
152  9 if (this.childrenMap.containsKey(key)) {
153  9 return this.childrenMap.get(key);
154    }
155  200 } else if (this.childrenMap.containsKey(key)) {
156  148 final Components value = this.childrenMap.get(key);
157    // TODO i don't know if good idea, but it's works.
158  148 if (value.size() > 1) {
159  0 return value;
160    }
161  148 return value.first();
162    }
163    }
164  52 return null;
165    }
166   
 
167  269 toggle public Map<String, String> getAttrs() {
168  269 return this.attributes;
169    }
170   
 
171  1 toggle public String getAttribute(String name) {
172  1 if (!this.attributes.containsKey(name)) {
173  0 return null;
174    }
175  1 return this.attributes.get(name);
176    }
177   
 
178  22 toggle public boolean hasAttribute(String name) {
179  22 return this.attributes.containsKey(name);
180    }
181   
182    /**
183    * @return the ARIA attributes
184    */
 
185  15 toggle public Map<String, String> getAriaAttributes() {
186  15 return this.attributes.entrySet()
187    .stream()
188    .filter(e -> e.getKey().startsWith("aria-"))
189    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
190    }
191   
192    /**
193    * @return the data attributes
194    */
 
195  15 toggle public Map<String, String> getDataAttributes() {
196  15 return this.attributes.entrySet()
197    .stream()
198    .filter(e -> e.getKey().startsWith("data-"))
199    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
200    }
201   
202    /**
203    * @return the children
204    */
 
205  382 toggle public Components getChildren() {
206  382 return children;
207    }
208   
 
209  0 toggle public Components getChildren(final String name) {
210  0 final String key = requireNonNull(name).toLowerCase();
211  0 if (this.childrenMap.containsKey(key)) {
212  0 return this.childrenMap.get(key);
213    }
214  0 return Components.empty();
215    }
216   
 
217  319 toggle public T addChild(final Component<?> component) {
218  319 final String key = component.getName();
219  319 Components value = null;
220  319 if (!this.childrenMap.containsKey(key)) {
221  284 value = new Components();
222  284 this.childrenMap.put(key, value);
223    } else {
224  35 value = this.childrenMap.get(key);
225    }
226  319 value.add(component);
227  319 this.children.add(component);
228  319 return self();
229    }
230   
 
231  370 toggle protected T withParent(final Component<?> parent) {
232  370 this.parent = parent;
233  370 return self();
234    }
235   
 
236  0 toggle @Nonnull
237    protected SnippetComponent<?> getRootParent() {
238  0 Component<?> parent = this.parent;
239  0 while (!(parent instanceof SnippetComponent<?>)) {
240  0 parent = parent.parent;
241    }
242  0 return (SnippetComponent<?>) parent;
243    }
244   
245    /**
246    * @param attrs
247    * list of attributes
248    * @return the fluent instance
249    */
 
250  370 toggle protected T addAttributes(@Nonnull final Attributes attrs) {
251  370 attrs.asList().stream().forEach(this::addAttribute);
252  370 return self();
253    }
254   
255    /**
256    * @param attr
257    * attribute
258    * @return the fluent instance
259    */
 
260  398 toggle protected T addAttribute(@Nonnull final Attribute attr) {
261  398 this.attributes.put(requireNonNull(attr.getKey()).toLowerCase(),
262  398 Strings.isNullOrEmpty(attr.getValue()) ? "true" : attr.getValue());
263  398 return self();
264    }
265   
266    /**
267    * @return the fluent instance
268    */
 
269  1457 toggle @SuppressWarnings("unchecked")
270    protected T self() {
271  1457 return (T) this;
272    }
273   
274    /**
275    * {@inheritDoc}
276    */
 
277  232 toggle @Override
278    public String toString() {
279  232 return MoreObjects.toStringHelper(this)
280    .add("name", this.getName())
281    .add("isHtmlTag", this.isHtmlTag())
282    .add("attributes", this.attributes)
283    .add("children", this.children.stream().map((cpt) -> cpt.getName()).collect(Collectors.toList()))
284    .toString();
285    }
286    }