/**
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.waveprotocol.wave.model.document.raw.impl;
import org.waveprotocol.wave.model.document.raw.RawDocument;
import org.waveprotocol.wave.model.document.raw.RawDocumentProviderImpl;
import org.waveprotocol.wave.model.document.util.XmlStringBuilder;
import org.waveprotocol.wave.model.util.OffsetList;
import org.waveprotocol.wave.model.util.Preconditions;
import java.util.Map;
/**
* Defines how the RawDocument interface is provided by the state in Node,
* Element and Text.
*
*/
public class RawDocumentImpl implements RawDocument<Node, Element, Text> {
/**
* Builder class for this document type.
*/
public static class Factory implements RawDocument.Factory<RawDocumentImpl> {
/**
* {@inheritDoc}
*/
public RawDocumentImpl create(String tagName, Map<String, String> attributes) {
return new RawDocumentImpl(tagName, attributes);
}
}
/** Singleton builder for documents of this type. */
public static final Factory BUILDER = new Factory();
/** Sample provider of this document implementation. */
public static final RawDocument.Provider<RawDocumentImpl> PROVIDER
= RawDocumentProviderImpl.create(BUILDER);
/** Root document element. */
private final Element documentElement;
/**
* Creates a RawDocumentImpl.
*
* @param tagName The tag name of the document element.
* @param attributes The attributes of the documentelement.
*/
RawDocumentImpl(String tagName, Map<String, String> attributes) {
this.documentElement = createElement(tagName, attributes);
}
/**
* {@inheritDoc}
*/
public Element getDocumentElement() {
return documentElement;
}
/**
* {@inheritDoc}
*/
public Element createElement(String tagName, Map<String, String> attributes,
Element parentElement, Node nodeAfter) {
Element el = createElement(tagName, attributes);
insertBefore(parentElement, el, nodeAfter);
return el;
}
/**
* Creates an element.
* This factory method is the only place where elements get created.
*
* @param tagName
* @param attributes
* @return the new element
*/
protected Element createElement(String tagName, Map<String, String> attributes) {
Element element = new Element(tagName);
for (Map.Entry<String, String> attribute : attributes.entrySet()) {
element.setAttribute(attribute.getKey(), attribute.getValue());
}
return element;
}
/**
* {@inheritDoc}
*/
public Text createTextNode(String data, Element parentElement, Node nodeAfter) {
Text node = new Text(data);
insertBefore(parentElement, node, nodeAfter);
return node;
}
/**
* {@inheritDoc}
*/
public Element getParentElement(Node node) {
return node.getParentElement();
}
/**
* {@inheritDoc}
*/
public short getNodeType(Node node) {
return node.getNodeType();
}
/**
* {@inheritDoc}
*/
public Node getFirstChild(Node node) {
return node.getFirstChild();
}
/**
* {@inheritDoc}
*/
public Node getLastChild(Node node) {
return node.getLastChild();
}
/**
* {@inheritDoc}
*/
public Node getPreviousSibling(Node node) {
return node.getPreviousSibling();
}
/**
* {@inheritDoc}
*/
public Node getNextSibling(Node node) {
return node.getNextSibling();
}
/**
* {@inheritDoc}
*/
public Node insertBefore(Element parent, Node newChild, Node refChild) {
return parent.insertBefore(newChild, refChild);
}
/**
* {@inheritDoc}
*/
public Node insertBefore(Element parent, Node from, Node to, Node refChild) {
for (Node newChild = from; newChild != to; ) {
Node next = newChild.getNextSibling();
parent.insertBefore(newChild, refChild);
newChild = next;
}
return from;
}
/**
* {@inheritDoc}
*/
public void removeChild(Element parent, Node oldChild) {
parent.removeChild(oldChild);
}
/**
* {@inheritDoc}
*/
public boolean isSameNode(Node node, Node other) {
return node == other;
}
/**
* {@inheritDoc}
*/
public Map<String,String> getAttributes(Element element) {
return element.getAttributes();
}
/**
* {@inheritDoc}
*/
public String getTagName(Element element) {
return element.getTagName();
}
/**
* {@inheritDoc}
*/
public String getAttribute(Element element, String name) {
return element.getAttribute(name);
}
/**
* {@inheritDoc}
*/
public void setAttribute(Element element, String name, String value) {
Preconditions.checkNotNull(value, "Null attribute value in setAttribute");
element.setAttribute(name, value);
}
/**
* {@inheritDoc}
*/
public void removeAttribute(Element element, String name) {
element.removeAttribute(name);
}
/**
* {@inheritDoc}
*/
public String getData(Text textNode) {
return textNode.getData();
}
/**
* {@inheritDoc}
*/
public int getLength(Text textNode) {
return textNode.getLength();
}
/**
* {@inheritDoc}
*/
public void appendData(Text textNode, String arg) {
textNode.appendData(arg);
}
/**
* {@inheritDoc}
*/
public void insertData(Text textNode, int offset, String arg) {
textNode.insertData(offset, arg);
}
/**
* {@inheritDoc}
*/
public void deleteData(Text textNode, int offset, int count) {
textNode.deleteData(offset, count);
}
/**
* {@inheritDoc}
*/
public Text splitText(Text textNode, int offset) {
return textNode.splitText(offset);
}
/**
* {@inheritDoc}
*/
public Text mergeText(Text secondSibling) {
Text previous = asText(getPreviousSibling(secondSibling));
if (previous != null) {
previous.appendData(secondSibling.getData());
return previous;
} else {
return null;
}
}
/**
* {@inheritDoc}
*/
public Element asElement(Node node) {
return node != null ? node.asElement() : null;
}
/**
* {@inheritDoc}
*/
public Text asText(Node node) {
return node != null ? node.asText() : null;
}
/**
* {@inheritDoc}
*/
public OffsetList.Container<Node> getIndexingContainer(Node domNode) {
return domNode.getIndexingContainer();
}
/**
* {@inheritDoc}
*/
public void setIndexingContainer(Node domNode, OffsetList.Container<Node> indexingContainer) {
domNode.setIndexingContainer(indexingContainer);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return XmlStringBuilder.outerXml(this).toString();
}
/**
* Gets the inner XML content of this document as a string.
*
* @return inner content of this document.
*/
public String innerXml() {
return XmlStringBuilder.createChildren(this, documentElement).toString();
}
}