Package com.thoughtworks.xstream.io

Source Code of com.thoughtworks.xstream.io.StatefulWriter

/*
* Copyright (C) 2006 Joe Walnes.
* Copyright (C) 2006, 2007 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
* Created on 15. March 2006 by Joerg Schaible
*/
package com.thoughtworks.xstream.io;

import com.thoughtworks.xstream.core.util.FastStack;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;


/**
* An wrapper for all {@link HierarchicalStreamWriter} implementations, that keeps the state.
* Writing in a wrong state will throw a {@link StreamException}, that wraps either an
* {@link IOException} (writing to a closed writer) or an {@link IllegalStateException}. The
* implementation will also track unbalanced nodes or multiple attributes with the same name.
*
* @author Jörg Schaible
* @since 1.2
*/
public class StatefulWriter extends WriterWrapper {

    /**
     * <code>STATE_OPEN</code> is the initial value of the writer.
     *
     * @since 1.2
     */
    public static int STATE_OPEN = 0;
    /**
     * <code>STATE_NODE_START</code> is the state of a new node has been started.
     *
     * @since 1.2
     */
    public static int STATE_NODE_START = 1;
    /**
     * <code>STATE_VALUE</code> is the state if the value of a node has been written.
     *
     * @since 1.2
     */
    public static int STATE_VALUE = 2;
    /**
     * <code>STATE_NODE_END</code> is the state if a node has ended
     *
     * @since 1.2
     */
    public static int STATE_NODE_END = 3;
    /**
     * <code>STATE_CLOSED</code> is the state if the writer has been closed.
     *
     * @since 1.2
     */
    public static int STATE_CLOSED = 4;

    private transient int state = STATE_OPEN;
    private transient int balance;
    private transient FastStack attributes;

    /**
     * Constructs a StatefulWriter.
     *
     * @param wrapped the wrapped writer
     * @since 1.2
     */
    public StatefulWriter(final HierarchicalStreamWriter wrapped) {
        super(wrapped);
        attributes = new FastStack(16);
    }

    public void startNode(final String name) {
        startNodeCommon();
        super.startNode(name);
    }

    public void startNode(final String name, final Class clazz) {
        startNodeCommon();
        super.startNode(name, clazz);
    }

    private void startNodeCommon() {
        checkClosed();
        if (state == STATE_VALUE) {
            // legal XML, but not in XStream ... ?
            throw new StreamException(new IllegalStateException("Opening node after writing text"));
        }
        state = STATE_NODE_START;
        ++balance;
        attributes.push(new HashSet());
    }

    public void addAttribute(String name, String value) {
        checkClosed();
        if (state != STATE_NODE_START) {
            throw new StreamException(new IllegalStateException("Writing attribute '"
                    + name
                    + "' without an opened node"));
        }
        Set currentAttributes = (Set)attributes.peek();
        if (currentAttributes.contains(name)) {
            throw new StreamException(new IllegalStateException("Writing attribute '"
                    + name
                    + "' twice"));
        }
        currentAttributes.add(name);
        super.addAttribute(name, value);
    }

    public void setValue(String text) {
        checkClosed();
        if (state != STATE_NODE_START) {
            // STATE_NODE_END is legal XML, but not in XStream ... ?
            throw new StreamException(new IllegalStateException(
                    "Writing text without an opened node"));
        }
        state = STATE_VALUE;
        super.setValue(text);
    }

    public void endNode() {
        checkClosed();
        if (balance-- == 0) {
            throw new StreamException(new IllegalStateException("Unbalanced node"));
        }
        attributes.popSilently();
        state = STATE_NODE_END;
        super.endNode();
    }

    public void flush() {
        checkClosed();
        super.flush();
    }

    public void close() {
        if (state != STATE_NODE_END && state != STATE_OPEN) {
            // calling close in a finally block should not throw again
            // throw new StreamException(new IllegalStateException("Closing with unbalanced tag"));
        }
        state = STATE_CLOSED;
        super.close();
    }

    private void checkClosed() {
        if (state == STATE_CLOSED) {
            throw new StreamException(new IOException("Writing on a closed stream"));
        }
    }

    /**
     * Retrieve the state of the writer.
     *
     * @return one of the states
     * @see #STATE_OPEN
     * @see #STATE_NODE_START
     * @see #STATE_VALUE
     * @see #STATE_NODE_END
     * @see #STATE_CLOSED
     * @since 1.2
     */
    public int state() {
        return state;
    }

    private Object readResolve() {
        attributes = new FastStack(16);
        return this;
    }
}
TOP

Related Classes of com.thoughtworks.xstream.io.StatefulWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.