/*****************************************************************************
* This file is part of Rinzo
*
* Author: Claudio Cancinos WWW: https://sourceforge.net/projects/editorxml Copyright (C): 2008, Claudio Cancinos
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this program; If not, see
* <http://www.gnu.org/licenses/>
****************************************************************************/
package com.amalto.workbench.widgets.xmlviewer.model.visitor;
import java.util.StringTokenizer;
import com.amalto.workbench.widgets.xmlviewer.model.XMLNode;
import com.amalto.workbench.widgets.xmlviewer.utils.FileUtils;
import com.amalto.workbench.widgets.xmlviewer.utils.XMLViewUtils;
/**
* This visitor creates a formated String from a node and his children.
*
* Improvements:
* 1) If I have something like: <servlet-name>StripesDispatcher</servlet-name> it might not pass it to 3 lines.
* 2) Take into account the previously formated node because of the CR. Because tags following a comment tag should not add an extra CR.
* This is really messy if I have something like this:
* <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
* <!-- Configuration -->
* <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
*
* NOTE: Maybe is not such a good idea that the elements right inside the root element are separated by CR :-\
* 3) Think about comments tags. I should let them to be separated as they want from anything else in order to gain clarity in the xml
*
*/
public class ToStringVisitor implements StringGeneratorVisitor {
private StringBuffer buffer = new StringBuffer();
private int identation = 0;
private boolean addLineSeparator = true;
public boolean visitStart(XMLNode node) {
if(this.identation >0) {
this.addLineSeparator();
}
this.addIdentation();
this.addLine(node.getContent());
this.identation++;
if(!node.hasChildren()) {
this.addLineSeparator = false;
}
return true;
}
public boolean visitEnd(XMLNode node) {
this.identation--;
if(this.addLineSeparator) {
this.addLineSeparator();
this.addIdentation();
} else {
this.addLineSeparator = true;
}
this.addLine(node.getCorrespondingNode().getContent());
return true;
}
public boolean visitChild(XMLNode node) {
String content = node.getContent();
String trimmedContent = ""; //$NON-NLS-1$
if(node.isTextTag() || node.isCdata()) {
trimmedContent = content.trim();
if(XMLViewUtils.isEmpty(trimmedContent)) {
this.addBlankLines(content);
}
}
if(trimmedContent.length() > 0) {
boolean singleChild = node.getParent().getChildren().size() == 1;
if(node.isCommentTag() || node.isEmptyTag() || trimmedContent.length() > 60 || !singleChild) {
this.addLineSeparator();
this.addIdentation();
} else {
if(singleChild) {
this.addLineSeparator = false;
}
}
this.addLine(content);
}
return true;
}
private void addBlankLines(String content) {
int index = content.indexOf(FileUtils.LINE_SEPARATOR);
index = content.indexOf(FileUtils.LINE_SEPARATOR, index + 1);
while(index >= 0) {
this.addLineSeparator();
index = content.indexOf(FileUtils.LINE_SEPARATOR, index + 1);
}
}
private void addIdentation() {
for (int i = 0; i < identation; i++) {
this.buffer.append(this.getIndentToken());
}
}
private void addLineSeparator() {
this.buffer.append(FileUtils.LINE_SEPARATOR);
}
public void reset() {
this.buffer = new StringBuffer();
}
public String getString() {
return this.buffer.toString();
}
private void addLine(String line) {
if(line.length() <= this.getMaxLineLength()) {
this.buffer.append(line);
} else {
StringTokenizer tokenizer = new StringTokenizer(line, " "); //$NON-NLS-1$
StringBuffer currentLine = new StringBuffer();
StringBuffer finalLine = new StringBuffer();
while(tokenizer.hasMoreTokens()) {
while(tokenizer.hasMoreTokens() && currentLine.length() <= this.getMaxLineLength()) {
String nextToken = tokenizer.nextToken().trim();
currentLine.append((currentLine.toString().trim().length() == 0) ? nextToken : " " + nextToken); //$NON-NLS-1$
}
if(currentLine.length() != 0) {
if(tokenizer.hasMoreTokens()) {
currentLine.append(FileUtils.LINE_SEPARATOR);
}
finalLine.append(currentLine.toString());
currentLine = new StringBuffer();
for (int i = 0; i < identation + 1; i++) {
currentLine.append(this.getIndentToken());
}
}
}
this.buffer.append(finalLine.toString());
}
}
private int getMaxLineLength() {
return 1000;
}
private String getIndentToken() {
return FileUtils.TAB;
}
}