/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.ui.editors.dnd;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
public interface IElementGenerator {
public void setDataModel(Object object);
public String generateStartTag();
public String generateEndTag();
public static ElementNode SEPARATOR = new ElementNode(null, true) {
@Override
public void flush(NodeWriter writer, int indent) {
writer.next();
}
};
public static class NodeWriter {
static final String ECLIPSE_EDITORS_PLUGIN = "org.eclipse.ui.editors";
List<StringBuilder> builders = new ArrayList<StringBuilder>();
StringBuilder current = null;
boolean separate = true;
String indentUnit = "\t";
public static int getTabWidth() {
return Platform.getPreferencesService().getInt(ECLIPSE_EDITORS_PLUGIN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH, 4, new IScopeContext[]{InstanceScope.INSTANCE}); //$NON-NLS-1$
}
public static boolean useSpaces() {
return Platform.getPreferencesService().getBoolean(ECLIPSE_EDITORS_PLUGIN, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS, false, new IScopeContext[]{InstanceScope.INSTANCE}); //$NON-NLS-1$
}
public static String computeIndentUnit() {
if(!useSpaces()) {
return "\t";
}
int n = getTabWidth();
StringBuilder sb = new StringBuilder(n);
for (int i = 0; i < n; i++) sb.append(' ');
return sb.toString();
}
public NodeWriter(boolean separate) {
next();
this.separate = separate;
indentUnit = computeIndentUnit();
}
public void next() {
if(separate) {
while(current != null && current.length() > 0 && (current.charAt(current.length() - 1) == '\r'
|| current.charAt(current.length() - 1) == '\n')) {
current.setLength(current.length() - 1);
}
current = new StringBuilder();
builders.add(current);
}
}
public NodeWriter append(String s) {
current.append(s);
return this;
}
public String[] getResult() {
String[] result = new String[builders.size()];
for (int i = 0; i < result.length; i++) result[i] = builders.get(i).toString();
return result;
}
public String getText() {
if(builders.size() == 1) {
return builders.get(0).toString();
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < builders.size(); i++) result.append(builders.get(i).toString());
return result.toString();
}
public void appendIndent(int indent) {
for (int i = 0; i < indent; i++) {
append(indentUnit);
}
}
}
public static class NamedNode {
protected String name;
public static String escapeHtml(String text, boolean isAttribute) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
if(ch == '<') {
sb.append("<");
} else if(ch == '>') {
sb.append(">");
} else if(ch == '&' && !isEscapedSequence(text, i)) {
sb.append("&");
} else if(isAttribute && ch == '"') {
sb.append(""");
} else {
sb.append(ch);
}
}
return sb.toString();
}
static boolean isEscapedSequence(String text, int p) {
if(text.charAt(p) != '&') {
return false;
}
for (int i = p + 1; i < text.length(); i++) {
char ch = text.charAt(i);
if(ch == '&') return false;
if(ch == ';') return true;
}
return false;
}
public void flush(NodeWriter sb, int indent) {
}
}
public static class RootNode extends ElementNode {
public static ElementNode newRoot() {
return new RootNode();
}
public RootNode() {
super(null, false);
}
@Override
public void flush(NodeWriter sb, int indent) {
for (NamedNode c: children) {
c.flush(sb, indent);
}
}
}
public static class TextNode extends NamedNode {
public TextNode(String text) {
this.name = text;
}
@Override
public void flush(NodeWriter sb, int indent) {
if(indent >= 0) {
sb.appendIndent(indent);
}
sb.append(name);
if(indent >= 0) {
sb.append("\n");
}
}
}
/**
* Stores in a simple way html content to be flushed into text.
*
*/
public static class ElementNode extends NamedNode {
List<AttributeNode> attributes = new ArrayList<AttributeNode>();
List<NamedNode> children = new ArrayList<NamedNode>();
boolean empty;
String text = null;
public ElementNode(String name, boolean empty) {
this.name = name;
this.empty = empty;
}
public ElementNode(String name, String text) {
this.name = name;
this.text = (text == null) ? null : escapeHtml(text, false);
this.empty = text == null;
}
public void addAttribute(String name, String value) {
attributes.add(new AttributeNode(name, value));
}
public ElementNode addChild(String name) {
ElementNode c = new ElementNode(name, true);
children.add(c);
empty = false;
return c;
}
public CommentNode addComment(String text) {
CommentNode c = new CommentNode(text);
children.add(c);
empty = false;
return c;
}
public void addTextChild(String text) {
TextNode c = new TextNode(text);
children.add(c);
empty = false;
}
public ElementNode addChild(String name, String text) {
ElementNode c = new ElementNode(name, text);
children.add(c);
empty = false;
return c;
}
public List<NamedNode> getChildren() {
return children;
}
public void flush(NodeWriter sb, int indent) {
if(indent >= 0) {
sb.appendIndent(indent);
}
sb.append("<").append(name);
for (AttributeNode a: attributes) {
a.flush(sb);
}
if(empty) {
sb.append("/>");
} else if(text != null) {
sb.append(">");
for (NamedNode c: children) {
c.flush(sb, -1);
}
sb.append(text).append("</").append(name).append(">");
} else {
sb.append(">").append("\n");
for (NamedNode c: children) {
c.flush(sb, indent + 1);
}
sb.appendIndent(indent);
sb.append("</").append(name).append(">");
}
if(indent >= 0) {
sb.append("\n");
}
}
}
public static class CommentNode extends NamedNode {
public CommentNode(String text) {
name = text;
}
public void flush(NodeWriter sb, int indent) {
if(indent >= 0) {
sb.appendIndent(indent);
}
sb.append("<!-- ").append(name).append(" -->");
if(indent >= 0) {
sb.append("\n");
}
}
}
public static class AttributeNode extends NamedNode {
String value;
public AttributeNode(String name, String value) {
this.name = name;
this.value = escapeHtml(value, true);
}
public void flush(NodeWriter sb) {
sb.append(" ").append(name).append("=\"").append(value).append("\"");
}
}
}