All Downloads are FREE. Search and download functionalities are using the official Maven repository.

au.com.acegi.xmlformat.BlankLinesWriter Maven / Gradle / Ivy

The newest version!
/*-
 * #%L
 * XML Format Maven Plugin
 * %%
 * Copyright (C) 2011 - 2024 Acegi Technology Pty Limited
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

package au.com.acegi.xmlformat;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.StringTokenizer;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Node;
import org.dom4j.io.XMLWriter;

/**
 * Subclass of {@link XMLWriter} that preserves blank lines in outupt (at most
 * one of them, among two subsequent tags).
 */
class BlankLinesWriter extends XMLWriter {

  BlankLinesWriter(final OutputStream out, final XmlOutputFormat fmt)
      throws UnsupportedEncodingException {
    super(out, fmt);
  }

  @Override
  protected void writeString(final String text) throws IOException {
    if (text == null || text.length() == 0) {
      return;
    }

    String input = text;
    if (isEscapeText()) {
      input = escapeElementEntities(text);
    }

    if (getOutputFormat().isTrimText()) {
      boolean first = true;
      final StringTokenizer tokenizer = new StringTokenizer(input, " \t\r\f");

      final NewLinesHandler newLinesHandler = new NewLinesHandler();
      while (tokenizer.hasMoreTokens()) {
        final String token = tokenizer.nextToken();

        // Only if more tokens exist, continue
        if (newLinesHandler.processToken(token, tokenizer.hasMoreTokens())) {
          continue;
        }

        if (first) {
          first = false;
          if (lastOutputNodeType == Node.TEXT_NODE) {
            writer.write(" ");
          }
        } else {
          writer.write(" ");
        }

        writer.write(token.trim());
        lastOutputNodeType = Node.TEXT_NODE;
      }
      newLinesHandler.finished();
    } else {
      lastOutputNodeType = Node.TEXT_NODE;
      writer.write(input);
    }
  }

  private final class NewLinesHandler {
    private int newLinesCount;

    /**
     * Processes the token, counting the newlines and producing at most one in
     * output.
     *
     * @param token The token to be written
     * @param hasMoreTokens Does more tokens exist
     * @return True if the token needs to be skipped (it's a newline or a set of
     *         newlines)
     * @throws IOException If an I/O error occurs.
     */
    private boolean processToken(final String token, final boolean hasMoreTokens)
        throws IOException {
      final int tokenNewLines = StringUtils.countMatches(token, '\n');
      if (tokenNewLines > 0) {
        newLinesCount += tokenNewLines;
        return hasMoreTokens;
      }
      if (newLinesCount > 1) {
        writer.write("\n");
        newLinesCount = 0;
      }
      return false;
    }

    /**
     * Marks the end of token streams, allows to emit a last newlines if the last
     * tokens were all newlines.
     *
     * @throws IOException If an I/O error occurs.
     */
    private void finished() throws IOException {
      if (newLinesCount > 1) {
        writer.write("\n");
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy