001/*
002    Licensed to the Apache Software Foundation (ASF) under one
003    or more contributor license agreements.  See the NOTICE file
004    distributed with this work for additional information
005    regarding copyright ownership.  The ASF licenses this file
006    to you under the Apache License, Version 2.0 (the
007    "License"); you may not use this file except in compliance
008    with the License.  You may obtain a copy of the License at
009
010       http://www.apache.org/licenses/LICENSE-2.0
011
012    Unless required by applicable law or agreed to in writing,
013    software distributed under the License is distributed on an
014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015    KIND, either express or implied.  See the License for the
016    specific language governing permissions and limitations
017    under the License.
018 */
019
020package org.apache.wiki.util;
021
022import org.jdom2.Element;
023import org.jdom2.output.Format;
024import org.jdom2.output.XMLOutputter;
025
026/**
027 *  A utility class to generate XHTML objects and ultimately, serialised markup.
028 *  This class is incomplete but serves as a basic utility for JSPWiki, to be
029 *  expanded upon as needed.
030 *  <p>
031 *  This uses JDOM2 as its backing implementation.
032 *  </p>
033 *
034 *  <h3>Example</h3>
035 *  <p>
036 *  To generate a single element, an Element with PCDATA content, and then
037 *  embed the latter in the former:
038 *  </p>
039 *  <pre>
040 *    Element div = XhtmlUtil.element(XHTML.div);
041 *    Element p   = XhtmlUtil.element(XHTML.p,"Some content");
042 *    div.addContent(p);
043 *  </pre>
044 *  <p>
045 *  There is also a convenient link and link target constructor methods:
046 *  </p>
047 *  <pre>
048 *    Element link   = XhtmlUtil.link("hrefValue","linkText");
049 *    Element target = XhtmlUtil.target("targetIdValue","linkText");
050 *  </pre>
051 *
052 * @since 2.10
053 */
054public final class XhtmlUtil {
055
056    private XhtmlUtil() {}
057
058    /** to print <td></td> instead of <td /> */
059    public static final Format EXPAND_EMPTY_NODES = Format.getCompactFormat().setExpandEmptyElements( true );
060
061    /**
062     *  Serializes the Element to a String using a compact serialization format.
063     *
064     * @param element  the element to serialize.
065     * @return the serialized Element.
066     */
067    public static String serialize(final Element element ) {
068        return serialize( element, false );
069    }
070
071    /**
072     *  Serializes the Element to a String. If <tt>pretty</tt> is true,
073     *  uses a pretty whitespace format, otherwise a compact format.
074     *
075     * @param element  the element to serialize.
076     * @param pretty   if true, use a pretty whitespace format.
077     * @return the serialized Element.
078     */
079    public static String serialize(final Element element, final boolean pretty ) {
080        return serialize( element,pretty ? Format.getPrettyFormat() : Format.getCompactFormat() );
081    }
082
083    /**
084     *  Serializes the Element to a String. Allows to use a custom <tt>format</tt>.
085     *
086     * @param element  the element to serialize.
087     * @param format   custom <tt>format</tt> used to serialize the Element.
088     * @return the serialized Element.
089     */
090    public static String serialize(final Element element, final Format format ) {
091        final XMLOutputter out = new XMLOutputter( format );
092        return out.outputString( element );
093    }
094
095    /**
096     *  Return an Element with an element type name matching the parameter.
097     *
098     * @param element  the XHTML element type.
099     * @return a JDOM2 Element.
100     */
101    public static Element element(final XHTML element ) {
102        return element( element, null );
103    }
104
105    /**
106     *  Return an Element with an element type name matching the parameter,
107     *  and optional PCDATA (parsed character data, a String) content.
108     *
109     * @param element  the XHTML element type.
110     * @param content  the optional PCDATA content.
111     * @return a JDOM2 Element.
112     */
113    public static Element element(final XHTML element, final String content ) {
114        final Element elt = new Element( element.name() );
115        if( content != null ) {
116            elt.addContent( content );
117        }
118        return elt;
119    }
120
121    /**
122     *  Return an XHTML link with a required 'href' attribute value and optional link (PCDATA) content.
123     *
124     * @param href     the required 'href' value.
125     * @param content  the optional link (PCDATA) content.
126     * @return a JDOM2 Element.
127     */
128    public static Element link(final String href, final String content ) {
129        if( href == null ) {
130            throw new IllegalArgumentException("missing 'href' attribute value.");
131        }
132        return fLink(href,content,null);
133    }
134
135    /**
136     *  Return an XHTML link target with a required 'id' attribute value.
137     *
138     * @param id    the required 'id' link target value.
139     * @return a JDOM2 Element.
140     */
141    public static Element target(final String id, final String content ) {
142        if( id == null ) {
143            throw new IllegalArgumentException( "missing 'id' attribute value." );
144        }
145        return fLink( null, content, id );
146    }
147
148    /**
149     *  Return an XHTML link with an optional 'href' attribute, optional
150     *  link content, and optional 'id' link target value.
151     *
152     * @param href     the optional 'href' value.
153     * @param content  the optional link (PCDATA) content.
154     * @param id       the optional 'id' link target value.
155     * @return a JDOM2 Element.
156     */
157    private static Element fLink(final String href, final String content, final String id ) {
158        final Element a = element( XHTML.a );
159        if( href != null ) {
160            a.setAttribute( XHTML.ATTR_href, href );
161        }
162        if( content != null ) {
163            a.addContent( content );
164        }
165        if( id != null ) {
166            a.setAttribute( XHTML.ATTR_id, id );
167        }
168        return a;
169    }
170
171    /**
172     *  Return an XHTML <tt>img</tt> element with an required 'src' attribute
173     *  and optional 'alt' alternative text value.
174     *
175     * @param src      the required 'src' value.
176     * @param alt      the optional 'alt' alternative text value.
177     * @return a JDOM2 Element.
178     */
179    public static Element img(final String src, final String alt ) {
180        final Element img = element( XHTML.img );
181        if( src == null ) {
182            throw new IllegalArgumentException( "missing 'src' attribute value." );
183        }
184        img.setAttribute( XHTML.ATTR_src, src );
185        if( alt != null ) {
186            img.setAttribute( XHTML.ATTR_alt, alt );
187        }
188        return img;
189    }
190
191    /**
192     *  Return an XHTML form <tt>input</tt> element with optional 'type', 'name' and 'value' attributes.
193     *
194     * @param type   the optional 'type' value.
195     * @param name   the optional 'name' value.
196     * @param value  the optional 'value' value.
197     * @return a JDOM2 Element.
198     */
199    public static Element input(final String type, final String name, final String value ) {
200        final Element input = element( XHTML.input );
201        if( type != null ) {
202            input.setAttribute( XHTML.ATTR_type, type );
203        }
204        if( name != null ) {
205            input.setAttribute( XHTML.ATTR_name, name );
206        }
207        if( value != null ) {
208            input.setAttribute( XHTML.ATTR_value, value );
209        }
210        return input;
211    }
212
213    public static void setClass(final Element element, final String classValue ) {
214        if( classValue == null ) {
215            throw new IllegalArgumentException( "missing 'class' attribute value." );
216        }
217        element.setAttribute( XHTML.ATTR_class, classValue );
218    }
219
220}