001: /*
002: * Copyright (C) 2006, 2007 XStream Committers.
003: * All rights reserved.
004: *
005: * The software in this package is published under the terms of the BSD
006: * style license a copy of which has been included with this distribution in
007: * the LICENSE.txt file.
008: *
009: * Created on 18. October 2007 by Joerg Schaible
010: */
011: package com.thoughtworks.xstream.io.xml;
012:
013: import com.thoughtworks.xstream.core.util.FastStack;
014:
015: import java.util.ArrayList;
016: import java.util.List;
017:
018: /**
019: * A generic {@link com.thoughtworks.xstream.io.HierarchicalStreamWriter} for DOM writer
020: * implementations. The implementation manages a list of top level DOM nodes. Every time the
021: * last node is closed on the node stack, the next started node is added to the list. This list
022: * can be retrieved using the {@link DocumentWriter#getTopLevelNodes()} method.
023: *
024: * @author Laurent Bihanic
025: * @author Jörg Schaible
026: * @since 1.2.1
027: */
028: public abstract class AbstractDocumentWriter extends AbstractXmlWriter
029: implements DocumentWriter {
030:
031: private final List result = new ArrayList();
032: private final FastStack nodeStack = new FastStack(16);
033:
034: /**
035: * Constructs an AbstractDocumentWriter.
036: *
037: * @param container the top level container for the nodes to create (may be
038: * <code>null</code>)
039: * @param replacer the object that creates XML-friendly names
040: * @since 1.2.1
041: */
042: public AbstractDocumentWriter(final Object container,
043: final XmlFriendlyReplacer replacer) {
044: super (replacer);
045: if (container != null) {
046: nodeStack.push(container);
047: result.add(container);
048: }
049: }
050:
051: public final void startNode(final String name) {
052: final Object node = createNode(name);
053: nodeStack.push(node);
054: }
055:
056: /**
057: * Create a node. The provided node name is not yet XML friendly. If {@link #getCurrent()}
058: * returns <code>null</code> the node is a top level node.
059: *
060: * @param name the node name
061: * @return the new node
062: * @since 1.2.1
063: */
064: protected abstract Object createNode(String name);
065:
066: public final void endNode() {
067: endNodeInternally();
068: final Object node = nodeStack.pop();
069: if (nodeStack.size() == 0) {
070: result.add(node);
071: }
072: }
073:
074: /**
075: * Called when a node ends. Hook for derived implementations.
076: *
077: * @since 1.2.1
078: */
079: public void endNodeInternally() {
080: }
081:
082: /**
083: * @since 1.2.1
084: */
085: protected final Object getCurrent() {
086: return nodeStack.peek();
087: }
088:
089: public List getTopLevelNodes() {
090: return result;
091: }
092:
093: public void flush() {
094: // don't need to do anything
095: }
096:
097: public void close() {
098: // don't need to do anything
099: }
100: }
|