/******************************************************************************
* Copyright (c) 2016 Oracle
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ling Hao - initial implementation and ongoing maintenance
* Konstantin Komissarchik - [333782] Problems in whitespace handling
******************************************************************************/
package org.eclipse.sapphire.modeling.util.internal;
import org.eclipse.sapphire.modeling.docsys.BoldPart;
import org.eclipse.sapphire.modeling.docsys.CodePart;
import org.eclipse.sapphire.modeling.docsys.DocumentationContent;
import org.eclipse.sapphire.modeling.docsys.DocumentationPart;
import org.eclipse.sapphire.modeling.docsys.LineBreakPart;
import org.eclipse.sapphire.modeling.docsys.ListItem;
import org.eclipse.sapphire.modeling.docsys.ListPart;
import org.eclipse.sapphire.modeling.docsys.OrderedListPart;
import org.eclipse.sapphire.modeling.docsys.ParagraphBreakPart;
import org.eclipse.sapphire.modeling.docsys.TextPart;
import org.eclipse.sapphire.modeling.docsys.UnorderedListPart;
import org.eclipse.sapphire.services.StandardValueNormalizationService;
/**
* @author <a href="mailto:ling.hao@oracle.com">Ling Hao</a>
*/
public class DocumentationUtil {
public final static String NEW_LINE = System.getProperty("line.separator");
public final static String NEW_LINE_2 = NEW_LINE + NEW_LINE;
private final static String BOLD_BEGIN = "<@#$b>";
private final static String BOLD_END = "</@#$b>";
public final static String decodeDocumentationTags(final String str) {
if (str == null)
return str;
DocumentationContent content = DocumentationContent.parse(str.trim());
final StringBuilder buf = new StringBuilder();
FormatFlags flags = new FormatFlags();
format( buf, content, -1, flags );
return buf.toString();
}
private static boolean startsWithSpaces(final String text) {
final char ch = text.charAt( 0 );
return Character.isWhitespace( ch );
}
private static boolean endsWithSpaces(final String text) {
final char ch = text.charAt( text.length() - 1 );
return Character.isWhitespace( ch );
}
private static void format(final StringBuilder buf, final DocumentationPart part, int index, FormatFlags flags) {
boolean collapseSpaces = flags.collapseSpaces;
if (part instanceof TextPart) {
final String str = ((TextPart) part).getText();
final boolean endsWithSpace = endsWithSpaces(str);
final boolean startsWithSpace = startsWithSpaces(str);
if (startsWithSpace && buf.toString().endsWith(BOLD_END)) {
buf.append(' ');
}
buf.append(collapseSpaces ? StandardValueNormalizationService.collapse(str) : str);
flags.endsInSpace = endsWithSpace;
} else if (part instanceof LineBreakPart) {
buf.append(NEW_LINE);
flags.endsInSpace = false;
} else if (part instanceof ParagraphBreakPart) {
buf.append(NEW_LINE_2);
flags.endsInSpace = false;
} else if (part instanceof OrderedListPart) {
buf.append(NEW_LINE_2);
int childIndex = 0;
for (ListItem item : ((ListPart) part).getItems()) {
childIndex++;
format(buf, item, childIndex, flags);
}
} else if (part instanceof UnorderedListPart) {
buf.append(NEW_LINE_2);
for (ListItem item : ((ListPart) part).getItems()) {
format(buf, item, -1, flags);
}
} else if (part instanceof ListItem) {
buf.append(index == -1 ? "*" : index);
buf.append(" ");
for (DocumentationPart child : ((ListItem) part).getChildren()) {
format(buf, child, -1, flags);
}
buf.append(NEW_LINE);
flags.endsInSpace = false;
} else if (part instanceof BoldPart) {
BoldPart boldPart = (BoldPart)part;
if (boldPart.isOpen()) {
if (flags.endsInSpace) {
buf.append(' ');
}
buf.append(BOLD_BEGIN);
} else {
buf.append(BOLD_END);
}
} else if (part instanceof CodePart) {
CodePart codePart = (CodePart)part;
if (codePart.isOpen()) {
flags.collapseSpaces = false;
} else {
flags.collapseSpaces = true;
}
} else if (part instanceof DocumentationContent) {
for (DocumentationPart child : ((DocumentationContent) part).getChildren()) {
format(buf, child, -1, flags);
}
}
}
private static class FormatFlags {
boolean collapseSpaces = true;
boolean endsInSpace = false;
FormatFlags() {
}
}
}