View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2014 wcm.io
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package io.wcm.handler.commons.dom;
21  
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import org.apache.commons.lang3.StringUtils;
26  import org.osgi.annotation.versioning.ConsumerType;
27  
28  /**
29   * Html element wrapper object.
30   * This element class is an extension of JDOM Element.
31   */
32  @ConsumerType
33  @SuppressWarnings("java:S110") // # parent inheritance
34  public class HtmlElement extends AbstractHtmlElementFactory {
35  
36    private static final long serialVersionUID = 1L;
37  
38    private static final String ATTRIBUTE_ID = "id";
39    private static final String ATTRIBUTE_CLASS = "class";
40    private static final String ATTRIBUTE_STYLE = "style";
41    private static final String ATTRIBUTE_TITLE = "title";
42    private static final String ATTRIBUTE_DATA_PREFIX = "data-";
43  
44    /**
45     * Initializes html element.
46     * @param name Element name
47     */
48    public HtmlElement(String name) {
49      super(name);
50    }
51  
52    /**
53     * Appends the child to the end of the element's content list.
54     * Returns not the element itself (contrary to addContent), but a reference to the newly added element.
55     * @param <HtmlElementType> Type that extends HtmlElement
56     * @param element Element to add. Null values are ignored.
57     * @return The added element.
58     */
59    public final <HtmlElementType extends HtmlElement> HtmlElementType add(HtmlElementType element) {
60      this.addContent(element);
61      return element;
62    }
63  
64    /**
65     * Gets "empty" attribute value as boolean (i.e. for "checked" attribute).
66     * @param attributeName Attribute name
67     * @return Attribute value as boolean or false if not set.
68     */
69    protected final boolean getEmptyAttributeValueAsBoolean(String attributeName) {
70      return attributeName.equalsIgnoreCase(getAttributeValue(attributeName));
71    }
72  
73    /**
74     * Sets "empty" attribute value as boolean (i.e. for "checked" attribute).
75     * @param attributeName Attribute name
76     * @param value Attribute value as boolean
77     * @return Self reference
78     */
79    protected HtmlElement setEmptyAttributeValueAsBoolean(String attributeName, boolean value) {
80      if (value) {
81        setAttribute(attributeName, attributeName.toLowerCase());
82      }
83      else {
84        removeAttribute(attributeName);
85      }
86      return this;
87    }
88  
89    /**
90     * Html "id" attribute.
91     * @return Value of attribute
92     */
93    public final String getId() {
94      return getAttributeValue(ATTRIBUTE_ID);
95    }
96  
97    /**
98     * Html "id" attribute.
99     * @param value Value of attribute
100    * @return Self reference
101    */
102   public HtmlElement setId(String value) {
103     setAttribute(ATTRIBUTE_ID, value);
104     return this;
105   }
106 
107   /**
108    * Html "class" attribute.
109    * @return Value of attribute
110    */
111   public final String getCssClass() {
112     return getAttributeValue(ATTRIBUTE_CLASS);
113   }
114 
115   /**
116    * Sets Html "class" attribute - unless you're really sure that you want to replace existing classes,
117    * you probably should call {@link #addCssClass(String)} instead.
118    * @param value Value of attribute
119    * @return Self reference
120    */
121   public HtmlElement setCssClass(String value) {
122     setAttribute(ATTRIBUTE_CLASS, value);
123     return this;
124   }
125 
126   /**
127    * Html "class" attribute. Adds a single, space-separated value while preserving existing ones.
128    * @param value Value of attribute
129    * @return Self reference
130    */
131   public HtmlElement addCssClass(String value) {
132     if (StringUtils.isNotEmpty(value)) {
133       return setCssClass(StringUtils.isNotEmpty(getCssClass()) ? getCssClass() + " " + value : value);
134     }
135     else {
136       return this;
137     }
138   }
139 
140   /**
141    * Html "style" attribute.
142    * @return Value of attribute with style key/value pairs
143    */
144   public final String getStyleString() {
145     return getAttributeValue(ATTRIBUTE_STYLE);
146   }
147 
148   /**
149    * Html "style" attribute.
150    * @return Returns map of style key/value pairs.
151    */
152   public final Map<String, String> getStyles() {
153     Map<String, String> styleMap = new HashMap<>();
154 
155     // de-serialize style string, fill style map
156     String styleString = getStyleString();
157     if (styleString != null) {
158       String[] styles = StringUtils.split(styleString, ";");
159       for (String styleSubString : styles) {
160         String[] styleParts = StringUtils.split(styleSubString, ":");
161         if (styleParts.length > 1) {
162           styleMap.put(styleParts[0].trim(), styleParts[1].trim());
163         }
164       }
165     }
166 
167     return styleMap;
168   }
169 
170   /**
171    * Html "style" attribute. Returns single style attribute value.
172    * @param styleAttribute Style attribute name
173    * @return Style attribute value
174    */
175   public final String getStyle(String styleAttribute) {
176     return getStyles().get(styleAttribute);
177   }
178 
179   /**
180    * Html "style" attribute.
181    * @param value Value of attribute with style key/value pairs
182    * @return Self reference
183    */
184   public HtmlElement setStyleString(String value) {
185     setAttribute(ATTRIBUTE_STYLE, value);
186     return this;
187   }
188 
189   /**
190    * Html "style" attribute. Sets single style attribute value.
191    * @param styleAttribute Style attribute name
192    * @param styleValue Style attribute value
193    * @return Self reference
194    */
195   public HtmlElement setStyle(String styleAttribute, String styleValue) {
196 
197     // Add style to style map
198     Map<String, String> styleMap = getStyles();
199     styleMap.put(styleAttribute, styleValue);
200 
201     // Serialize style string
202     StringBuilder styleString = new StringBuilder();
203     for (Map.Entry<String, String> style : styleMap.entrySet()) {
204       styleString.append(style.getKey())
205         .append(':')
206         .append(style.getValue())
207         .append(';');
208     }
209     setStyleString(styleString.toString());
210     return this;
211   }
212 
213   /**
214    * Html "title" attribute.
215    * @return Value of attribute
216    */
217   public final String getTitle() {
218     return getAttributeValue(ATTRIBUTE_TITLE);
219   }
220 
221   /**
222    * Html "title" attribute.
223    * @param value Value of attribute
224    * @return Self reference
225    */
226   public HtmlElement setTitle(String value) {
227     setAttribute(ATTRIBUTE_TITLE, value);
228     return this;
229   }
230 
231   /**
232    * Custom Html5 "data-*" attribute.
233    * @param attributeName Name of HTML5 data attribute (without the 'data-' prefix).
234    * @return Value of attribute
235    */
236   public final String getData(String attributeName) {
237     return getAttributeValue(ATTRIBUTE_DATA_PREFIX + attributeName);
238   }
239 
240   /**
241    * Custom Html5 "data-*" attribute.
242    * @param attributeName Name of HTML5 data attribute (without the 'data-' prefix).
243    * @param value Value of attribute
244    * @return Self reference
245    */
246   public HtmlElement setData(String attributeName, String value) {
247     setAttribute(ATTRIBUTE_DATA_PREFIX + attributeName, value);
248     return this;
249   }
250 
251 }