All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.directwebremoting.json.parse.impl.StatefulJsonDecoder Maven / Gradle / Ivy

Go to download

DWR is easy Ajax for Java. It makes it simple to call Java code directly from Javascript. It gets rid of almost all the boiler plate code between the web browser and your Java code.

The newest version!
/*
 * Copyright 2005 Joe Walker
 *
 * 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.directwebremoting.json.parse.impl;

import java.math.BigDecimal;
import java.util.LinkedList;

import org.directwebremoting.json.parse.JsonDecoder;
import org.directwebremoting.json.parse.JsonParseException;

/**
 * A stateful implementation of {@link JsonDecoder} where we track the stack
 * of objects and allow a subclass to have a simpler set of things to do
 * @author Joe Walker [joe at getahead dot ltd dot uk]
 */
public abstract class StatefulJsonDecoder implements JsonDecoder
{
    /**
     * Create a new object.
     * This method should not actually add the object to the parent.
     * That will be done by {@link #addMemberToArray(Object, Object)}
     * @param parent The parent object that this will be added to. This will be
     * null if we are creating the root object
     * @param propertyName The member name if we are adding a property to an
     * object or null if we are adding to an array
     */
    protected abstract Object createObject(Object parent, String propertyName) throws JsonParseException;

    /**
     * Create a new array.
     * This method should not actually add the object to the parent.
     * That will be done by {@link #addMemberToArray(Object, Object)}
     * @param parent The parent object that this will be added to. This will be
     * null if we are creating the root object
     * @param propertyName The member name if we are adding a property to an
     * object or null if we are adding to an array
     */
    protected abstract Object createArray(Object parent, String propertyName) throws JsonParseException;

    /**
     * Add the given value to the propertyName property
     * of the parent object.
     * @throws JsonParseException If there are any errors in adding the value
     */
    protected abstract void addMemberToObject(Object parent, String propertyName, Object member) throws JsonParseException;

    /**
     * Add the given value to the parent array.
     * @throws JsonParseException If there are any errors in adding the value
     */
    protected abstract void addMemberToArray(Object parent, Object member) throws JsonParseException;

    /* (non-Javadoc)
     * @see org.directwebremoting.json.parse.JsonDecoder#getRoot()
     */
    public Object getRoot() throws JsonParseException
    {
        return last;
    }

    /* (non-Javadoc)
     * @see org.directwebremoting.json.parse.impl.StatefulJsonDecoder#beginObject()
     */
    public void beginObject(String propertyName) throws JsonParseException
    {
        Object obj = createObject(stackPeek(), propertyName);
        stack.addLast(obj);
    }

    /* (non-Javadoc)
     * @see org.directwebremoting.json.parse.impl.StatefulJsonDecoder#endObject()
     */
    public void endObject(String propertyName) throws JsonParseException
    {
        this.last = stack.removeLast();

        // Don't try to add the top level object to its parent
        if (!stack.isEmpty())
        {
            add(propertyName, last);
        }
    }

    /* (non-Javadoc)
     * @see org.directwebremoting.json.parse.impl.StatefulJsonDecoder#beginArray()
     */
    public void beginArray(String propertyName) throws JsonParseException
    {
        Object obj = createArray(stackPeek(), propertyName);
        stack.addLast(obj);
    }

    /* (non-Javadoc)
     * @see org.directwebremoting.json.parse.impl.StatefulJsonDecoder#endArray()
     */
    public void endArray(String propertyName) throws JsonParseException
    {
        this.last = stack.removeLast();

        // Don't add the top level object to its parent
        if (!stack.isEmpty())
        {
            add(propertyName, last);
        }
    }

    /**
     * Add the add methods do basically the same thing - add themselves to the
     * current object or array.
     */
    public void add(String propertyName, Object value) throws JsonParseException
    {
        if (propertyName == null)
        {
            addMemberToArray(stackPeek(), value);
        }
        else
        {
            addMemberToObject(stackPeek(), propertyName, value);
        }
    }

    /* (non-Javadoc)
     * @see org.directwebremoting.json.parse.JsonDecoder#addString(java.lang.String)
     */
    public void addString(String propertyName, String value) throws JsonParseException
    {
        add(propertyName, value);
    }

    /* (non-Javadoc)
     * @see org.directwebremoting.json.parse.JsonDecoder#addNumber(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
     */
    public void addNumber(String propertyName, String intPart, String floatPart, String expPart) throws JsonParseException
    {
        Object value = realizeNumber(intPart, floatPart, expPart);
        add(propertyName, value);
    }

    /* (non-Javadoc)
     * @see org.directwebremoting.json.parse.JsonDecoder#addBoolean(boolean)
     */
    public void addBoolean(String propertyName, boolean value) throws JsonParseException
    {
        add(propertyName, value);
    }

    /* (non-Javadoc)
     * @see org.directwebremoting.json.parse.JsonDecoder#addNull()
     */
    public void addNull(String propertyName) throws JsonParseException
    {
        add(propertyName, null);
    }

    /**
     * Peek at the top of the stack without changing it, or return null if there
     * is nothing on the stack.
     */
    protected Object stackPeek()
    {
        if (stack.isEmpty())
        {
            return null;
        }
        else
        {
            return stack.getLast();
        }
    }

    /**
     * The stack of objects that we have created. Sometimes (particularly with
     * objects there are a number of states within an object, so we need to
     * maintain a separate mode stack.
     */
    protected final LinkedList stack = new LinkedList();

    /**
     * {@link #getRoot()} is called after we have removed the last object on the
     * stack, so we need to remember what it was.
     */
    protected Object last = null;

    /**
     * Create a {@link BigDecimal}, double, int, or long depending on the input
     * strings.
     * @param intPart A string of [0-9]* representing the integer part of the
     * number.
     * @param floatPart A string of \.[0-9]* representing the floating point part
     * of the number. This INCLUDES the period
     * @param expPart A string of [eE][+-]?[0-9]* representing the integer part
     * of the number. This includes the 'e' or 'E'.
     */
    public static Object realizeNumber(String intPart, String floatPart, String expPart)
    {
        if (expPart != null)
        {
            return new BigDecimal(intPart + floatPart + expPart);
        }
        else if (floatPart != null)
        {
            return Double.parseDouble(intPart + floatPart);
        }
        else
        {
            try
            {
                return Integer.parseInt(intPart);
            }
            catch (NumberFormatException ex)
            {
                try
                {
                    return Long.parseLong(intPart);
                }
                catch (NumberFormatException ex2)
                {
                    return new BigDecimal(intPart);
                }
            }
        }
    }
}