SquirrelJME/SquirrelJME

View on GitHub
modules/json/src/main/java/net/multiphasicapps/jsr353/ImplValueArray.java

Summary

Maintainability
A
0 mins
Test Coverage
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the Mozilla Public License Version 2.0.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package net.multiphasicapps.jsr353;

import cc.squirreljme.runtime.cldc.debug.Debugging;
import com.oracle.json.JsonArray;
import com.oracle.json.JsonNumber;
import com.oracle.json.JsonObject;
import com.oracle.json.JsonString;
import com.oracle.json.JsonValue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import net.multiphasicapps.collections.UnmodifiableList;

/**
 * This is an array of values.
 *
 * @since 2014/08/05
 */
public class ImplValueArray
    extends AbstractList<JsonValue>
    implements JsonArray
{
    /** Internal list. */
    private final List<JsonValue> _il;    
    
    /**
     * Initializes list of values from the base list.
     *
     * @param __b Base list to use.
     * @since 2014/08/05
     */
    public ImplValueArray(List<JsonValue> __b)
    {
        // Cannot be null
        if (__b == null)
            throw new NullPointerException(
                "No value list specified.");
        
        // Lock on that value, although it may not matter much
        synchronized (__b)
        {
            // Copy through them all, they are immutable always
            List<JsonValue> n = new ArrayList<JsonValue>(__b);
            
            // Set internal list as read-only
            this._il = UnmodifiableList.of(n); 
        }
    }
    
    /**
     * Returns the element at the specified index.
     *
     * @param __i Index to obtain the value from.
     * @throws IndexOutOfBoundsException If this is out of bounds.
     * @return The element at this index.
     * @since 2014/08/05
     */
    @Override
    public JsonValue get(int __i)
    {
        return this._il.get(__i);
    }
    
    /**
     * Returns the size of this array.
     *
     * @return The size of this array.
     * @since 2014/08/05
     */
    @Override
    public int size()
    {
        return this._il.size();
    }
    
    /**
     * Returns the type of value this is.
     *
     * @return The type of value that this is.
     * @since 2014/08/05
     */
    @Override
    public ValueType getValueType()
    {
        return ValueType.ARRAY;
    }
    
    /**
     * Returns the string representation of this value.
     *
     * @return The value of this array represented as a string.
     * @since 2014/08/05
     */
    @SuppressWarnings("StringOperationCanBeSimplified")
    @Override
    public String toString()
    {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
            OutputStreamWriter writer = new OutputStreamWriter(baos))
        {
            new ImplWriter(writer, false).write(this);
            writer.flush();
            
            return new String(baos.toByteArray(), "utf-8");
        }
        catch (IOException e)
        {
            throw Debugging.oops(e);
        }
    }
    
    /**
     * Returns the boolean value at the specified position, {@code true} is
     * returned if it is {@link JsonValue#TRUE}, otherwise {@code false} is
     * returned if it is {@link JsonValue#FALSE}.
     *
     * @param __i Index into the array to look up.
     * @return The boolean value at the specified index.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @throws ClassCastException If the specific value is not
     * {@link JsonValue#TRUE} or {@link JsonValue#FALSE}.
     * @since 2014/08/05
     */
    @Override
    public boolean getBoolean(int __i)
    {
        JsonValue bv = this.get(__i);
        
        // True
        if (bv == JsonValue.TRUE)
            return true;
        
        // False
        else if (bv == JsonValue.FALSE)
            return false;
        
        // Error
        else
            throw new ClassCastException(
                "Not a boolean value.");
    }
    
    /**
     * This is similar to {@link #getBoolean(int)} except that if the value is
     * not a boolean, it returns {@code __def}.
     *
     * @param __i Index into the array to look up.
     * @param __def Default value if this is not a boolean.
     * @return The specified boolean value or {@code __def}.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @since 2014/08/05
     */
    @Override
    public boolean getBoolean(int __i, boolean __def)
    {
        // Return boolean value
        try
        {
            return this.getBoolean(__i);
        }
        
        // Not a boolean
        catch (Exception e)
        {
            // Rethrow if out of bounds
            if (e instanceof IndexOutOfBoundsException)
                throw (IndexOutOfBoundsException)e;
            
            return __def;
        }
    }
    
    /**
     * Invokes {@code getNumber(__i).intValue()}.
     *
     * @param __i Index into the array to look up.
     * @return The integer value.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @throws ClassCastException If the value is not assignable to
     * {@link JsonNumber}.
     * @since 2014/08/05
     */
    @Override
    public int getInt(int __i)
    {
        return this.getNumber(__i).intValue();
    }
    
    /**
     * Similar to {@link #getInt(int)} except that if the value is not a
     * number, {@code __def} is returned.
     *
     * @param __i Index into the array to look up.
     * @param __def Default value, if not an integer.
     * @return The integer value or {@code __def}.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @since 2014/08/05
     */
    @Override
    public int getInt(int __i, int __def)
    {
        try
        {
            return this.getInt(__i);
        }
        
        // Return default
        catch (Exception e)
        {
            // Rethrow if out of bounds
            if (e instanceof IndexOutOfBoundsException)
                throw (IndexOutOfBoundsException)e;
            
            return __def;
        }
    }
    
    /**
     * Invokes {@code (JsonArray)get(__i)}.
     *
     * @param __i Index into the array to look up.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @throws ClassCastException If the value is not assignable to
     * {@link JsonArray}.
     * @since 2014/08/05
     */
    @Override
    public JsonArray getArray(int __i)
    {
        return (JsonArray)this.get(__i);
    }
    
    /**
     * Invokes {@code (JsonNumber)get(__i)}.
     *
     * @param __i Index into the array to look up.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @throws ClassCastException If the value is not assignable to
     * {@link JsonNumber}.
     * @since 2014/08/05
     */
    @Override
    public JsonNumber getNumber(int __i)
    {
        return (JsonNumber)this.get(__i);
    }
    
    /**
     * Invokes {@code (JsonObject)get(__i)}.
     *
     * @param __i Index into the array to look up.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @throws ClassCastException If the value is not assignable to
     * {@link JsonObject}.
     * @since 2014/08/05
     */
    @Override
    public JsonObject getObject(int __i)
    {
        return (JsonObject)this.get(__i);
    }
    
    /**
     * Invokes {@code (JsonString)get(__i)}.
     *
     * @param __i Index into the array to look up.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @throws ClassCastException If the value is not assignable to
     * {@link JsonString}.
     * @since 2014/08/05
     */
    @Override
    public JsonString getJsonString(int __i)
    {
        return (JsonString)this.get(__i);
    }
    
    /**
     * Invokes {@code getJsonString(__i).getString()}.
     *
     * @param __i Index into the array to look up.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @throws ClassCastException If the value is not assignable to
     * {@link JsonString}.
     * @since 2014/08/05
     */
    @Override
    public String getString(int __i)
    {
        return this.getJsonString(__i).getString();
    }
    
    /**
     * Similar to {@link #getString(int)} except that if the value is not a
     * string, {@code __def} is returned.
     *
     * @param __i Index into the array to look up.
     * @param __def Default value, if not a string.
     * @return The string value or {@code __def}.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @since 2014/08/05
     */
    @Override
    public String getString(int __i, String __def)
    {
        // Obtain
        try
        {
            return this.getString(__i);
        }
        
        // Failed
        catch (Exception e)
        {
            // Rethrow if out of bounds
            if (e instanceof IndexOutOfBoundsException)
                throw (IndexOutOfBoundsException)e;
            
            return __def;
        }
    }
    
    /**
     * Returns an unmodifiable view of the specified array, no checking is
     * performed therefor it is possible that {@link ClassCastException} may
     * be thrown when the list is used.
     *
     * @param <T> Type to view the list as.
     * @param __cl The class value for T.
     * @return {@link List} view of the specified array.
     * @since 2014/08/05
     */
    @Override
    public <T extends JsonValue> List<T> getValueAs(Class<T> __cl)
    {
        // Must extend JsonValue
        if (!JsonValue.class.isAssignableFrom(__cl))
            throw new ClassCastException(
                "Class does not extend JsonValue.");
        
        // Return it
        return Unchecked.<List<JsonValue>, List<T>>cast(
            UnmodifiableList.of(this));
    }
    
    /**
     * Returns {@code true} if the specified index is a {@link JsonValue#NULL}.
     *
     * @param __i Index into the array to look up.
     * @throws IndexOutOfBoundsException If the index is out of range.
     * @since 2014/08/05
     */
    @Override
    public boolean isNull(int __i)
    {
        // Get and check
        JsonValue jv = this.get(__i);
        return (jv == JsonValue.NULL);
    }
}