1. Project Clover database mer. févr. 4 2026 12:48:28 CET
  2. Package org.devacfr.maven.skins.reflow.snippet

File Component.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart9.png
20% 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 19
0.833333383,3%
 

Contributing tests

This file is covered by 36 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  666 toggle public static Component<?> createComponent(@Nonnull final Node node, final Component<?> parent) {
71  666 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  774 toggle protected Component(@Nonnull final Node node) {
79  774 this.node = requireNonNull(node);
80    }
81   
82    /**
83    * @return the name
84    */
 
85  2158 toggle public String getName() {
86  2158 return node.nodeName();
87    }
88   
89    /**
90    * @return
91    */
 
92  1180 toggle public boolean isHtmlTag() {
93  1180 return node instanceof TextNode || Tag.isKnownTag(node.nodeName()) || knownTags.contains(node.nodeName());
94    }
95   
96    /**
97    * @return the html content
98    */
 
99  660 toggle public String getHtml() {
100  660 if (!isHtmlTag()) {
101  254 if (children.isEmpty()) {
102  24 return "";
103    } else {
104  230 return children.html();
105    }
106    } else {
107  406 return this.node.outerHtml();
108    }
109    }
110   
111    /**
112    * @return
113    */
 
114  30 toggle public String getOwnHtml() {
115  30 if (!isHtmlTag()) {
116  6 return null;
117    } else {
118  24 return this.node.outerHtml();
119    }
120    }
121   
122    /**
123    * @return the parent
124    */
 
125  18 toggle public Component<?> getParent() {
126  18 return parent;
127    }
128   
 
129  106 toggle @Nullable protected Element getElement() {
130  106 if (this.node instanceof Element) {
131  106 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  672 toggle public Object get(@Nonnull final String name) {
142  672 requireNonNull(name);
143  672 String key = name.toLowerCase();
144    // if attribute
145  672 if (this.attributes.containsKey(key)) {
146  204 return this.attributes.get(key);
147    } else {
148    // is children component?
149    // check if 's' suffix allowing to retrieve children component as list
150  468 if (key.endsWith("s") && !this.childrenMap.containsKey(key)) {
151  16 key = key.substring(0, key.length() - 1);
152  16 if (this.childrenMap.containsKey(key)) {
153  16 return this.childrenMap.get(key);
154    }
155  452 } else if (this.childrenMap.containsKey(key)) {
156  306 final Components value = this.childrenMap.get(key);
157    // TODO i don't know if good idea, but it's works.
158  306 if (value.size() > 1) {
159  2 return value;
160    }
161  304 return value.first();
162    }
163    }
164  146 return null;
165    }
166   
 
167  560 toggle public Map<String, String> getAttrs() {
168  560 return this.attributes;
169    }
170   
 
171  2 toggle public String getAttribute(String name) {
172  2 if (!this.attributes.containsKey(name)) {
173  0 return null;
174    }
175  2 return this.attributes.get(name);
176    }
177   
 
178  44 toggle public boolean hasAttribute(String name) {
179  44 return this.attributes.containsKey(name);
180    }
181   
182    /**
183    * @return the ARIA attributes
184    */
 
185  30 toggle public Map<String, String> getAriaAttributes() {
186  30 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  30 toggle public Map<String, String> getDataAttributes() {
196  30 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  798 toggle public Components getChildren() {
206  798 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  668 toggle public T addChild(final Component<?> component) {
218  668 final String key = component.getName();
219  668 Components value = null;
220  668 if (!this.childrenMap.containsKey(key)) {
221  598 value = new Components();
222  598 this.childrenMap.put(key, value);
223    } else {
224  70 value = this.childrenMap.get(key);
225    }
226  668 value.add(component);
227  668 this.children.add(component);
228  668 return self();
229    }
230   
 
231  774 toggle protected T withParent(final Component<?> parent) {
232  774 this.parent = parent;
233  774 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  774 toggle protected T addAttributes(@Nonnull final Attributes attrs) {
251  774 attrs.asList().stream().forEach(this::addAttribute);
252  774 return self();
253    }
254   
255    /**
256    * @param attr
257    * attribute
258    * @return the fluent instance
259    */
 
260  830 toggle protected T addAttribute(@Nonnull final Attribute attr) {
261  830 this.attributes.put(requireNonNull(attr.getKey()).toLowerCase(),
262  830 Strings.isNullOrEmpty(attr.getValue()) ? "true" : attr.getValue());
263  830 return self();
264    }
265   
266    /**
267    * @return the fluent instance
268    */
 
269  3046 toggle @SuppressWarnings("unchecked")
270    protected T self() {
271  3046 return (T) this;
272    }
273   
274    /**
275    * {@inheritDoc}
276    */
 
277  472 toggle @Override
278    public String toString() {
279  472 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    }