/******************************************************************************* * 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("\""); } } }