package com.onaro.client.leekui.ui; import java.util.ArrayList; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import com.onaro.client.leekui.ui.internal.WorkbenchPlugin; /** * This class represents the default implementation of the IMemento interface. *

* This class is not intended to be extended by clients. *

* * @see IMemento * This class is a reimplementation of the Eclipse class org.eclipse.ui.XMLMemento */ public final class XMLMemento implements IMemento { /** * Returns a root memento for writing a document. * * @param type the element node type to create on the document * @return the root memento for writing a document */ public static XMLMemento createWriteRoot(String type) { Document document; try { document = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); Element element = document.createElement(type); document.appendChild(element); return new XMLMemento(document, element); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } } private final Document factory; private final Element element; public XMLMemento(Element element) { this(element.getOwnerDocument(), element); } /** * Creates a memento for the specified document and element. * * @param document * the document for the memento * @param element * the element node for the memento */ public XMLMemento(Document document, Element element) { super(); this.factory = document; this.element = element; } /* * (non-Javadoc) Method declared in IMemento. */ public IMemento createChild(String type) { return createChild(type,StringUtils.EMPTY); } /* * (non-Javadoc) Method declared in IMemento. */ public IMemento createChild(String type, String id) { Element child = factory.createElement(type); child.setAttribute(TAG_ID, id == null ? StringUtils.EMPTY : id); element.appendChild(child); return new XMLMemento(factory, child); } /* * (non-Javadoc) Method declared in IMemento. */ public IMemento getChild(String type) { // Get the nodes. NodeList nodes = element.getChildNodes(); int size = nodes.getLength(); if (size == 0) { return null; } // Find the first node which is a child of this node. for (int nX = 0; nX < size; nX++) { Node node = nodes.item(nX); if (node instanceof Element) { Element element = (Element) node; if (element.getNodeName().equals(type)) { return new XMLMemento(factory, element); } } } // A child was not found. return null; } /* * (non-Javadoc) Method declared in IMemento. */ public IMemento[] getChildren(String type) { // Get the nodes. NodeList nodes = element.getChildNodes(); int size = nodes.getLength(); if (size == 0) { return new IMemento[0]; } // Extract each node with given type. ArrayList list = new ArrayList(size); for (int nX = 0; nX < size; nX++) { Node node = nodes.item(nX); if (node instanceof Element) { Element element = (Element) node; if (element.getNodeName().equals(type)) { list.add(element); } } } // Create a memento for each node. size = list.size(); IMemento[] results = new IMemento[size]; for (int x = 0; x < size; x++) { results[x] = new XMLMemento(factory, list.get(x)); } return results; } /* * (non-Javadoc) Method declared in IMemento. */ public Float getFloat(String key) { Attr attr = element.getAttributeNode(key); if (attr == null) { return null; } String strValue = attr.getValue(); try { return new Float(strValue); } catch (NumberFormatException e) { WorkbenchPlugin.log("Memento problem - Invalid float for key: " + key + " value: " + strValue, e); //$NON-NLS-1$ //$NON-NLS-2$ return null; } } /* * (non-Javadoc) Method declared in IMemento. */ public String getID() { return element.getAttribute(TAG_ID); } /* * (non-Javadoc) Method declared in IMemento. */ public Integer getInteger(String key) { Attr attr = element.getAttributeNode(key); if (attr == null) { return null; } String strValue = attr.getValue(); try { return Integer.valueOf(strValue); } catch (NumberFormatException e) { WorkbenchPlugin.log("Memento problem - invalid integer for key: " + key + " value: " + strValue, e); //$NON-NLS-1$ //$NON-NLS-2$ return null; } } /* * (non-Javadoc) Method declared in IMemento. */ public String getString(String key) { Attr attr = element.getAttributeNode(key); if (attr == null) { return null; } return attr.getValue(); } /* * (non-Javadoc) Method declared in IMemento. */ public String getTextData() { Text textNode = getTextNode(); if (textNode != null) { return textNode.getData(); } return null; } /** * Returns the Text node of the memento. Each memento is allowed only one Text node. * * @return the Text node of the memento, or null if the memento has no Text node. */ private Text getTextNode() { // Get the nodes. NodeList nodes = element.getChildNodes(); int size = nodes.getLength(); if (size == 0) { return null; } for (int nX = 0; nX < size; nX++) { Node node = nodes.item(nX); if (node instanceof Text) { return (Text) node; } } // a Text node was not found return null; } /** * Places the element's attributes into the document. * * @param copyText * true if the first text node should be copied */ private void putElement(Element element, boolean copyText) { NamedNodeMap nodeMap = element.getAttributes(); int size = nodeMap.getLength(); for (int i = 0; i < size; i++) { Attr attr = (Attr) nodeMap.item(i); putString(attr.getName(), attr.getValue()); } NodeList nodes = element.getChildNodes(); size = nodes.getLength(); // Copy first text node (fixes bug 113659). // Note that text data will be added as the first child (see putTextData) boolean needToCopyText = copyText; for (int i = 0; i < size; i++) { Node node = nodes.item(i); if (node instanceof Element) { XMLMemento child = (XMLMemento) createChild(node.getNodeName()); child.putElement((Element) node, true); } else if (node instanceof Text && needToCopyText) { putTextData(((Text) node).getData()); needToCopyText = false; } } } /* * (non-Javadoc) Method declared in IMemento. */ public void putFloat(String key, float f) { element.setAttribute(key, String.valueOf(f)); } /* * (non-Javadoc) Method declared in IMemento. */ public void putInteger(String key, int n) { element.setAttribute(key, String.valueOf(n)); } /* * (non-Javadoc) Method declared in IMemento. */ public void putMemento(IMemento memento) { // Do not copy the element's top level text node (this would overwrite the existing text). // Text nodes of children are copied. putElement(((XMLMemento) memento).element, false); } /* * (non-Javadoc) Method declared in IMemento. */ public void putString(String key, String value) { if (value == null) { return; } element.setAttribute(key, value); } /* * (non-Javadoc) Method declared in IMemento. */ public void putTextData(String data) { Text textNode = getTextNode(); if (textNode == null) { textNode = factory.createTextNode(data); // Always add the text node as the first child (fixes bug 93718) element.insertBefore(textNode, element.getFirstChild()); } else { textNode.setData(data); } } public Element getElement() { return element; } }