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 */ 019package org.apache.maven.doxia.sink.impl; 020 021import javax.swing.text.MutableAttributeSet; 022import javax.swing.text.html.HTML.Tag; 023 024import java.util.Objects; 025 026import org.apache.maven.doxia.markup.HtmlTag; 027import org.apache.maven.doxia.markup.XmlMarkup; 028 029/** 030 * An abstract <code>Sink</code> for xml markup syntax. 031 * 032 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a> 033 * @since 1.0 034 */ 035public abstract class AbstractXmlSink extends SinkAdapter implements XmlMarkup { 036 /** Default namespace prepended to all tags */ 037 private String nameSpace; 038 039 private boolean firstTag = true; 040 041 private boolean insertNewline = true; 042 043 /** 044 * <p>Setter for the field <code>insertNewline</code>.</p> 045 * 046 * @param insertNewline a boolean. 047 */ 048 public void setInsertNewline(boolean insertNewline) { 049 this.insertNewline = insertNewline; 050 } 051 052 /** 053 * Sets the default namespace that is prepended to all tags written by this sink. 054 * 055 * @param ns the default namespace. 056 * @since 1.1 057 */ 058 public void setNameSpace(String ns) { 059 this.nameSpace = ns; 060 } 061 062 /** 063 * Return the default namespace that is prepended to all tags written by this sink. 064 * 065 * @return the current default namespace. 066 * @since 1.1 067 */ 068 public String getNameSpace() { 069 return this.nameSpace; 070 } 071 072 /** 073 * Starts a Tag. For instance: 074 * <pre> 075 * <tag> 076 * </pre> 077 * 078 * @param t a non null tag 079 * @see #writeStartTag(HtmlTag, javax.swing.text.MutableAttributeSet) 080 * @deprecated use {@link #writeStartTag(HtmlTag)}; the {@code javax.swing} tag type goes in 2.3.0. 081 */ 082 @Deprecated 083 protected void writeStartTag(Tag t) { 084 writeStartTag(t, null); 085 } 086 087 /** 088 * Starts a Tag with attributes. For instance: 089 * <pre> 090 * <tag attName="attValue"> 091 * </pre> 092 * 093 * @param t a non null tag. 094 * @param att a set of attributes. May be null. 095 * @see #writeStartTag(HtmlTag, javax.swing.text.MutableAttributeSet, boolean) 096 * @deprecated use {@link #writeStartTag(HtmlTag, javax.swing.text.MutableAttributeSet)}; the 097 * {@code javax.swing} tag type goes in 2.3.0. 098 */ 099 @Deprecated 100 protected void writeStartTag(Tag t, MutableAttributeSet att) { 101 writeStartTag(t, att, false); 102 } 103 104 /** 105 * Starts a Tag with attributes. For instance: 106 * <pre> 107 * <tag attName="attValue"> 108 * </pre> 109 * 110 * @param t a non null tag. 111 * @param att a set of attributes. May be null. 112 * @param isEmptyElement boolean to write as tag for an <a href="https://www.w3.org/TR/xml/#d0e2480">empty element</a>. 113 * @deprecated use {@link #writeStartTag(HtmlTag, javax.swing.text.MutableAttributeSet, boolean)}; the 114 * {@code javax.swing} tag type goes in 2.3.0. 115 */ 116 @Deprecated 117 protected void writeStartTag(Tag t, MutableAttributeSet att, boolean isEmptyElement) { 118 writeStartTag(toHtmlTag(t), att, isEmptyElement); 119 } 120 121 /** 122 * Starts a Tag. For instance: 123 * <pre> 124 * <tag> 125 * </pre> 126 * 127 * @param t a non null tag 128 * @see #writeStartTag(HtmlTag, javax.swing.text.MutableAttributeSet) 129 * @since 2.2.0 130 */ 131 protected void writeStartTag(HtmlTag t) { 132 writeStartTag(t, null); 133 } 134 135 /** 136 * Starts a Tag with attributes. For instance: 137 * <pre> 138 * <tag attName="attValue"> 139 * </pre> 140 * 141 * @param t a non null tag. 142 * @param att a set of attributes. May be null. 143 * @see #writeStartTag(HtmlTag, javax.swing.text.MutableAttributeSet, boolean) 144 * @since 2.2.0 145 */ 146 protected void writeStartTag(HtmlTag t, MutableAttributeSet att) { 147 writeStartTag(t, att, false); 148 } 149 150 /** 151 * Starts a Tag with attributes. For instance: 152 * <pre> 153 * <tag attName="attValue"> 154 * </pre> 155 * 156 * @param t a non null tag. 157 * @param att a set of attributes. May be null. 158 * @param isEmptyElement boolean to write as tag for an <a href="https://www.w3.org/TR/xml/#d0e2480">empty element</a>. 159 * @since 2.2.0 160 */ 161 protected void writeStartTag(HtmlTag t, MutableAttributeSet att, boolean isEmptyElement) { 162 Objects.requireNonNull(t, "t cannot be null"); 163 164 StringBuilder sb = new StringBuilder(); 165 166 if (insertNewline && t.isBlock() && !firstTag) { 167 sb.append(EOL); 168 } 169 firstTag = false; 170 171 sb.append(LESS_THAN); 172 173 if (nameSpace != null) { 174 sb.append(nameSpace).append(':'); 175 } 176 177 sb.append(t.toString()); 178 179 sb.append(SinkUtils.getAttributeString(att)); 180 181 if (isEmptyElement) { 182 sb.append(SPACE).append(SLASH); 183 } 184 185 sb.append(GREATER_THAN); 186 187 write(sb.toString()); 188 } 189 190 /** 191 * Writes a system EOL. 192 * 193 * @since 1.1 194 */ 195 protected void writeEOL() { 196 write(EOL); 197 } 198 199 /** 200 * Ends a Tag without writing an EOL. For instance: <pre></tag></pre>. 201 * 202 * @param t a tag. 203 * @deprecated use {@link #writeEndTag(HtmlTag)}; the {@code javax.swing} tag type goes in 2.3.0. 204 */ 205 @Deprecated 206 protected void writeEndTag(Tag t) { 207 writeEndTag(toHtmlTag(t)); 208 } 209 210 /** 211 * Ends a Tag without writing an EOL. For instance: <pre></tag></pre>. 212 * 213 * @param t a tag. 214 * @since 2.2.0 215 */ 216 protected void writeEndTag(HtmlTag t) { 217 Objects.requireNonNull(t, "t cannot be null"); 218 219 StringBuilder sb = new StringBuilder(); 220 sb.append(LESS_THAN); 221 sb.append(SLASH); 222 223 if (nameSpace != null) { 224 sb.append(nameSpace).append(':'); 225 } 226 227 sb.append(t.toString()); 228 sb.append(GREATER_THAN); 229 230 write(sb.toString()); 231 } 232 233 /** 234 * Starts a simple Tag. For instance: 235 * <pre> 236 * <tag /> 237 * </pre> 238 * 239 * @param t a non null tag 240 * @see #writeSimpleTag(HtmlTag, javax.swing.text.MutableAttributeSet) 241 * @deprecated use {@link #writeSimpleTag(HtmlTag)}; the {@code javax.swing} tag type goes in 2.3.0. 242 */ 243 @Deprecated 244 protected void writeSimpleTag(Tag t) { 245 writeSimpleTag(t, null); 246 } 247 248 /** 249 * Starts a simple Tag with attributes. For instance: 250 * <pre> 251 * <tag attName="attValue" /> 252 * </pre> 253 * 254 * @param t a non null tag. 255 * @param att a set of attributes. May be null. 256 * @see #writeStartTag(HtmlTag, javax.swing.text.MutableAttributeSet, boolean) 257 * @deprecated use {@link #writeSimpleTag(HtmlTag, javax.swing.text.MutableAttributeSet)}; the 258 * {@code javax.swing} tag type goes in 2.3.0. 259 */ 260 @Deprecated 261 protected void writeSimpleTag(Tag t, MutableAttributeSet att) { 262 writeStartTag(t, att, true); 263 } 264 265 /** 266 * Starts a simple Tag. For instance: 267 * <pre> 268 * <tag /> 269 * </pre> 270 * 271 * @param t a non null tag 272 * @see #writeSimpleTag(HtmlTag, javax.swing.text.MutableAttributeSet) 273 * @since 2.2.0 274 */ 275 protected void writeSimpleTag(HtmlTag t) { 276 writeSimpleTag(t, null); 277 } 278 279 /** 280 * Starts a simple Tag with attributes. For instance: 281 * <pre> 282 * <tag attName="attValue" /> 283 * </pre> 284 * 285 * @param t a non null tag. 286 * @param att a set of attributes. May be null. 287 * @see #writeStartTag(HtmlTag, javax.swing.text.MutableAttributeSet, boolean) 288 * @since 2.2.0 289 */ 290 protected void writeSimpleTag(HtmlTag t, MutableAttributeSet att) { 291 writeStartTag(t, att, true); 292 } 293 294 /** 295 * Returns the Doxia tag of the same name, falling back to a tag that answers exactly as the 296 * given one does, so that a tag Doxia does not declare keeps its own block value. 297 */ 298 private static HtmlTag toHtmlTag(Tag t) { 299 Objects.requireNonNull(t, "t cannot be null"); 300 301 HtmlTag known = HtmlTag.valueOf(t.toString()); 302 303 return known != null ? known : new HtmlTag(t.toString(), t.isBlock()); 304 } 305 306 /** 307 * Write a text to the sink. 308 * 309 * @param text the given text to write 310 */ 311 protected abstract void write(String text); 312}