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