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

io.vertigo.quarto.plugins.publisher.odt.ODTCleanerUtil Maven / Gradle / Ivy

There is a newer version: 0.9.4
Show newest version
/**
 * vertigo - simple java starter
 *
 * Copyright (C) 2013, KleeGroup, [email protected] (http://www.kleegroup.com)
 * KleeGroup, Centre d'affaire la Boursidiere - BP 159 - 92357 Le Plessis Robinson Cedex - France
 *
 * 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.
 */
package io.vertigo.quarto.plugins.publisher.odt;

import io.vertigo.util.StringUtil;

import java.util.Stack;

import org.apache.log4j.Logger;

/**
 * Classe de nettoyage d'une arborescence XML.
 * Gestion du cas ou il y a des balises ouvertes non fermées.
 *
 * @author brenard
 */
final class ODTCleanerUtil {

	private static final Logger LOGGER = Logger.getLogger(ODTCleanerUtil.class);

	/**
	 * Constructeur privé pour classe utilitaire.
	 */
	private ODTCleanerUtil() {
		//RAS
	}

	/**
	 * Corrige le contenu qui est une arborescence XML pour gérer le cas
	 * ou il y a des balises ouvertes non fermées.
	 *
	 * @param xmlContent Arborescence XML.
	 * @return Arborescence nettoyée.
	 */
	static String clean(final String xmlContent) {
		final StringBuilder contentClean = new StringBuilder();
		cleanContent(xmlContent.toCharArray(), contentClean);
		return contentClean.toString();
	}

	private static void cleanContent(final char[] content, final StringBuilder contentClean) {
		final Stack pileBalise = new Stack<>();

		// On parcours le contenu
		char current;
		final StringBuilder currentOuvrante = new StringBuilder();
		final StringBuilder currentFermante = new StringBuilder();
		boolean baliseOuvrante = false;
		boolean baliseOuvranteEnCours = false;
		boolean baliseFermante = false;
		boolean baliseFermanteEnCours = false;

		final int length = content.length;
		for (int i = 0; i < length; i++) {
			current = content[i];
			// debut de balise
			if (current == '<') {
				// On regarde s'il s'agit d'une ouverture ou d'une fermeture
				if (content[i + 1] == '/') {
					baliseFermante = true;
					baliseFermanteEnCours = true;
					i += 2;
					current = content[i];
				} else if (content[i + 1] != ' ') {
					contentClean.append(current);
					i++;
					current = content[i];
					baliseOuvrante = true;
					baliseOuvranteEnCours = true;
				}
			}

			// On ajoute le contenu courant que dans le cas ou l'on ne traite pas de
			// balise fermante. En effet si la balise fermante courante ne correspond
			// pas à le dernière balise ouvrante alors il faut inserer la bonne avant
			// de mettre la balise fermante courante.
			if (!baliseFermanteEnCours) {
				contentClean.append(current);
			}

			// Cas particulier du 
			if (baliseOuvrante && current == '?') {
				currentOuvrante.setLength(0);
				baliseOuvrante = false;
				baliseOuvranteEnCours = false;
			}

			// Si on rencontre un de ces caractères alors on connait le nom de la balise
			// ouvrante
			if (baliseOuvrante && (current == '/' || current == ' ' || current == '>')) {
				baliseOuvrante = false;
			}

			// On ajoute la balise ouvrante dans la pile lorsque l'on a atteind
			// le signe de fermeture
			if (current == '>' && baliseOuvranteEnCours) {
				if (content[i - 1] != '/') {
					pileBalise.push(currentOuvrante.toString());
				}
				baliseOuvranteEnCours = false;
				currentOuvrante.setLength(0);
			}

			// Lorsque l'on a atteind la fin de la balise fermante alors on regarde
			// si elle correspond bien à la dernière balise ouvrante
			if (baliseFermante && current == '>') {
				fermeBalisesOuvertes(contentClean, pileBalise, currentFermante);
				currentFermante.setLength(0);
				baliseFermante = false;
				baliseFermanteEnCours = false;
			}

			if (baliseOuvrante) {
				currentOuvrante.append(current);
			}

			if (baliseFermante) {
				currentFermante.append(current);
			}
		}
	}

	private static void fermeBalisesOuvertes(final StringBuilder contentClean, final Stack pileBalise, final StringBuilder currentFermante) {
		//Si la balise fermante n'est pas présent dans la pile des balises déjà ouvertes, c'est qu'elle a disparu lors de la fusion,
		//on retire alors la balise fermante (corrige le nullPointer lors des pop() ).
		if (!pileBalise.contains(currentFermante.toString())) {
			LOGGER.warn(StringUtil.format("La balise fermante  n'est plus ouverte dans le document généré, elle est retiré du document.", currentFermante));
		} else {
			String lastBalise = pileBalise.pop();
			//Tant que la balise fermante ne correspond pas à la
			// balise ouvrante alors on ferme les balises ouvrantes
			while (currentFermante.length() != lastBalise.length() && currentFermante.indexOf(lastBalise) != 0) {
				contentClean.append("');
				lastBalise = pileBalise.pop();
			}
			contentClean.append("');
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy