Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.m2e.model.edit/src/main/java/org/eclipse/m2e/model/edit/pom/translators/TranslatorAdapter.java')
-rw-r--r--org.eclipse.m2e.model.edit/src/main/java/org/eclipse/m2e/model/edit/pom/translators/TranslatorAdapter.java371
1 files changed, 371 insertions, 0 deletions
diff --git a/org.eclipse.m2e.model.edit/src/main/java/org/eclipse/m2e/model/edit/pom/translators/TranslatorAdapter.java b/org.eclipse.m2e.model.edit/src/main/java/org/eclipse/m2e/model/edit/pom/translators/TranslatorAdapter.java
new file mode 100644
index 00000000..c7250fdb
--- /dev/null
+++ b/org.eclipse.m2e.model.edit/src/main/java/org/eclipse/m2e/model/edit/pom/translators/TranslatorAdapter.java
@@ -0,0 +1,371 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.model.edit.pom.translators;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import com.ibm.icu.lang.UCharacter;
+
+
+/**
+ * A base class for all adapters that can translate a EMF to DOM and vice-versa.
+ *
+ * Each translator adaptor is expected to have a single root element that
+ * controls its existence. It is responsible for the subtree of that node by
+ * updating it directly or delegating to child adapters to do the work.
+ *
+ *
+ * @author Mike Poindexter
+ */
+public abstract class TranslatorAdapter implements INodeAdapter {
+ protected SSESyncResource resource;
+
+ protected Element node;
+
+ public TranslatorAdapter(SSESyncResource resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * Returns the textual value of an element.
+ *
+ * @param e
+ * @return
+ */
+ protected static String getElementText(Element e) {
+ StringBuilder ret = new StringBuilder();
+ NodeList children = e.getChildNodes();
+ int nChildren = children.getLength();
+ for (int i = 0; i < nChildren; i++) {
+ Node child = children.item(i);
+ if (child instanceof Text) {
+ ret.append(((Text) child).getData());
+ }
+ }
+ return ret.toString().trim();
+ }
+
+ /**
+ * Load the model value from this adapter's xml value
+ */
+ public abstract void load();
+
+ /**
+ * Save the xml value of this adapter from the model.
+ */
+ public abstract void save();
+
+ /**
+ * @param oldValue
+ */
+ public abstract void update(Object oldValue, Object newValue, int index);
+
+ /**
+ * Returns the index of the given element in the list of elements of the
+ * same name.
+ *
+ * @param e
+ * @return
+ */
+ protected int namedIndexOf(Element parentNode, Element element) {
+ int ret = 0;
+ NodeList children = parentNode.getChildNodes();
+ int nChildren = children.getLength();
+ for (int i = 0; i < nChildren; i++) {
+ Node child = children.item(i);
+ if (child instanceof Element) {
+ Element e = (Element) child;
+ if (e.getLocalName().equals(element.getLocalName())) {
+ if (e == element) {
+ return ret;
+ } else {
+ ret++;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the index of the given element in the list of child elements.
+ *
+ * @param e
+ * @return
+ */
+ protected int absoluteIndexOf(Element parentNode, Element element) {
+ int ret = 0;
+ NodeList children = parentNode.getChildNodes();
+ int nChildren = children.getLength();
+ for (int i = 0; i < nChildren; i++) {
+ Node child = children.item(i);
+ if (child instanceof Element) {
+ Element e = (Element) child;
+ if (e.getLocalName().equals(element.getLocalName())) {
+ if (e == element) {
+ return ret;
+ } else {
+ ret++;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the first child with the given name, or null if none exists.
+ *
+ * @param name
+ * @return
+ */
+ protected Element getFirstChildWithName(Element parent, String name) {
+ return getNthChildWithName(parent, name, 0);
+ }
+
+ /**
+ * Returns the nth child element with a given name, or null if no such
+ * element exists.
+ *
+ * @param name
+ * @param n
+ * @return
+ */
+ protected Element getNthChildWithName(Element parent, String name, int n) {
+ int matchCount = 0;
+ NodeList children = parent.getChildNodes();
+ int nChildren = children.getLength();
+ for (int i = 0; i < nChildren; i++) {
+ Node child = children.item(i);
+ if (child instanceof Element) {
+ Element e = (Element) child;
+ if (e.getTagName().equals(name) || "*".equals(name)) { //$NON-NLS-1$
+ if (matchCount == n) {
+ return e;
+ } else {
+ matchCount++;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public Element getNode() {
+ return node;
+ }
+
+ public void setNode(Element node) {
+ this.node = node;
+ }
+
+ protected void formatNode(Element element) {
+ createWSBefore(element);
+ createWSAfter(element);
+ }
+
+ /**
+ * Ensure at least one NL between this node and the previous, and proper
+ * start tag indentation.
+ *
+ * @param element
+ * @return
+ */
+ protected void createWSBefore(Element element) {
+ try {
+ IStructuredDocument doc = ((IDOMNode) element)
+ .getStructuredDocument();
+ int nodeStartOff = ((IDOMNode) element).getStartOffset();
+ StringBuilder betweenText = new StringBuilder();
+ int i = nodeStartOff - 1;
+ while (i > -1) {
+ char next = doc.getChar(i);
+ if (next == '>') {
+ break;
+ }
+ betweenText.insert(0, next);
+ i--;
+ }
+ int origLen = betweenText.length();
+ int nlIndex = betweenText.lastIndexOf("\n"); //$NON-NLS-1$
+ if (nlIndex == -1) {
+ String nl = getNewlineString();
+ betweenText.insert(0, nl);
+ nlIndex = nl.length() - 1;
+ }
+
+ String indent = getIndentForNode(element);
+ if (!indent.equals(betweenText.substring(nlIndex + 1))) {
+ betweenText.replace(nlIndex + 1, betweenText.length(), indent);
+ }
+ if (origLen > 0) {
+ doc.replaceText(this, i + 1, origLen, betweenText.toString());
+ } else {
+ Text t = element.getOwnerDocument().createTextNode(
+ betweenText.toString());
+ element.getParentNode().insertBefore(t, element);
+ }
+ } catch (BadLocationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Ensure at least one NL between this node and the next, and proper indent
+ * to the next tag tag indentation.
+ *
+ * @param element
+ * @return
+ */
+ protected void createWSAfter(Element element) {
+ try {
+ IStructuredDocument doc = ((IDOMNode) element)
+ .getStructuredDocument();
+ int nodeEndOff = ((IDOMNode) element).getEndOffset();
+ StringBuilder betweenText = new StringBuilder();
+ int i = nodeEndOff;
+ while (i < doc.getLength()) {
+ char next = doc.getChar(i);
+ if (next == '<') {
+ break;
+ }
+ betweenText.append(next);
+ i++;
+ }
+ int origLen = betweenText.length();
+ int nlIndex = betweenText.lastIndexOf("\n"); //$NON-NLS-1$
+ if (nlIndex == -1) {
+ String nl = getNewlineString();
+ betweenText.insert(0, nl);
+ nlIndex = nl.length() - 1;
+ }
+
+ Node refNode = element.getNextSibling();
+ while (refNode != null && !(refNode instanceof Element)) {
+ refNode = refNode.getNextSibling();
+ }
+ String indent = ""; //$NON-NLS-1$
+ if (refNode == null) {
+ indent = getIndentBeforeStartTag(element.getParentNode());
+ } else {
+ indent = getIndentForNode((Element) refNode);
+ }
+ if (!indent.equals(betweenText.substring(nlIndex + 1))) {
+ betweenText.replace(nlIndex + 1, betweenText.length(), indent);
+ }
+ if (origLen > 0) {
+ doc.replaceText(this, nodeEndOff, origLen, betweenText
+ .toString());
+ } else {
+ Text t = element.getOwnerDocument().createTextNode(
+ betweenText.toString());
+
+ if (null == refNode) {
+ element.getParentNode().appendChild(t);
+ } else {
+ element.getParentNode().insertBefore(t, refNode);
+ }
+ }
+ } catch (BadLocationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ protected void removeChildElement(Element e) {
+ IStructuredDocument doc = ((IDOMNode) e).getStructuredDocument();
+ int nodeStartOff = ((IDOMNode) e).getStartOffset();
+ int nodeEndOff = ((IDOMNode) e).getEndOffset();
+ int i = nodeStartOff - 1;
+
+ while (i > 0) {
+ char c = ' ';
+ try {
+ c = doc.getChar(i);
+ } catch (BadLocationException ble) {
+ // We check for bad locations so this should not happen
+ }
+ if(UCharacter.isWhitespace(c)) {
+ i--;
+ }
+
+ if (c == '\n') {
+ if (i > 0) {
+ try {
+ c = doc.getChar(i);
+ } catch (BadLocationException ble) {
+ // We check for bad locations so this should not happen
+ }
+ if (c == '\r')
+ i--;
+ }
+ break;
+ }
+
+ }
+ doc.replaceText(this, i + 1, nodeEndOff - i - 1, null);
+ }
+
+ private String getIndentForNode(Element node) {
+ String ret = null;
+ Node prev = node.getPreviousSibling();
+ while (prev != null) {
+ if (prev instanceof Element) {
+ ret = getIndentBeforeStartTag(prev);
+ break;
+ }
+ prev = prev.getPreviousSibling();
+ }
+
+ if (null == ret) {
+ ret = getIndentBeforeStartTag(node.getParentNode()) + "\t"; //$NON-NLS-1$
+ }
+ return ret;
+ }
+
+ private String getIndentBeforeStartTag(Node node) {
+ StringBuilder builder = new StringBuilder(100);
+ IStructuredDocument doc = ((IDOMNode) node).getStructuredDocument();
+ int nodeStartOff = ((IDOMNode) node).getStartOffset();
+ int i = nodeStartOff - 1;
+ while (i > 0) {
+ char c = ' ';
+ try {
+ c = doc.getChar(i);
+ } catch (BadLocationException e) {
+ // We check for bad locations so this should not happen
+ }
+ if(UCharacter.isWhitespace(c) && !(c == '\r' || c == '\n')) {
+ builder.insert(0, c);
+ i--;
+ } else {
+ break;
+ }
+ }
+ return builder.toString();
+ }
+
+ private String getNewlineString() {
+ return ((IDOMNode) node).getStructuredDocument().getLineDelimiter();
+ }
+
+}

Back to the top