/*
* Copyright (C) 2011 René Jeschke <rene_jeschke@yahoo.de>
*
* 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 com.github.rjeschke.weel;
/**
* A Weel value.
*
* @author René Jeschke <rene_jeschke@yahoo.de>
*/
public final class Value
{
/** This Value's type. */
ValueType type;
/** This Value's double value. */
double number;
/** This Value's object. */
Object object;
/**
* Creates a Value of type NULL.
*/
public Value()
{
this.type = ValueType.NULL;
}
/**
* Creates a Value of type NUMBER.
*
* @param value
* The value.
*/
public Value(final int value)
{
this.type = ValueType.NUMBER;
this.number = value;
}
/**
* Creates a Value of type NUMBER.
*
* @param value
* The value.
*/
public Value(final double value)
{
this.type = ValueType.NUMBER;
this.number = value;
}
/**
* Creates a Value of type STRING.
*
* @param value
* The value.
*/
public Value(final String value)
{
this.type = ValueType.STRING;
this.object = value;
}
/**
* Creates a Value of type MAP.
*
* @param value
* The value.
*/
public Value(final ValueMap value)
{
this.type = ValueType.MAP;
this.object = value;
}
/**
* Creates a Value of type FUNCTION.
*
* @param value
* The value.
*/
public Value(final WeelFunction value)
{
this.type = ValueType.FUNCTION;
this.object = value;
}
/**
* Creates a Value of type OBJECT.
*
* @param value
* The value.
*/
public Value(final Object value)
{
this.type = ValueType.OBJECT;
this.object = value;
}
/**
* Changes the type of this Value to <code>NULL</code>, clears references.
*/
public void setNull()
{
this.type = ValueType.NULL;
this.number = 0;
this.object = null;
}
/**
* Returns a boolean interpretation of this value.
*
* <ul>
* <li><code>NULL</code> returns <code>false</code></li>
* <li>A <code>NUMBER</code> equal to 0 returns <code>false</code></li>
* <li>A <code>STRING</code> with a length of 0 returns <code>false</code></li>
* <li>A <code>MAP</code> with a length of 0 returns <code>false</code></li>
* <li>A <code>OBJECT</code> with a value of null returns <code>false</code>
* </li>
* <li>Everything else returns <code>true</code></li>
* </ul>
*
* @return A boolean interpretation of this value.
*/
public boolean toBoolean()
{
switch (this.type)
{
case NULL:
return false;
case STRING:
return ((String)this.object).length() > 0;
case NUMBER:
return this.number != 0;
case MAP:
return ((ValueMap)this.object).size != 0;
case OBJECT:
return this.object != null;
default:
return true;
}
}
/**
* Copies this value into another.
*
* @param other
* Value to copy to.
*/
public void copyTo(final Value other)
{
other.type = this.type;
other.number = this.number;
other.object = this.object;
}
/** @see java.lang.Object#clone() */
@Override
public Value clone()
{
final Value v = new Value();
this.copyTo(v);
return v;
}
/**
* Returns an internal String representation of this value.
*
* @return The String.
*/
public String toIntString()
{
switch (this.type)
{
case NULL:
return "null";
case NUMBER:
{
// Hack
final long temp = (long)this.number;
if(temp == this.number)
return Long.toString(temp);
return Double.toString(this.number);
}
case STRING:
return "\"" + InstrLoad.escape((String)this.object) + "\"";
case MAP:
return ((ValueMap)this.object).toString();
case FUNCTION:
return ((WeelFunction)this.object).toString();
case OBJECT:
return this.object.toString();
}
return "null";
}
/** @see java.lang.Object#toString() */
@Override
public String toString()
{
switch (this.type)
{
case NULL:
return "null";
case NUMBER:
{
// Hack
final long temp = (long)this.number;
if(temp == this.number)
return Long.toString(temp);
return Double.toString(this.number);
}
case STRING:
return (String)this.object;
case MAP:
return ((ValueMap)this.object).toString();
case FUNCTION:
return ((WeelFunction)this.object).toString();
case OBJECT:
return this.object.toString();
}
return "null";
}
/**
* Gets this Value's type.
*
* @return The type of this value.
*/
public ValueType getType()
{
return this.type;
}
/**
* Check if this Value is NULL.
*
* @return <code>true</code> if this Value is NULL.
*/
public boolean isNull()
{
return this.type == ValueType.NULL;
}
/**
* Check if this Value is a NUMBER.
*
* @return <code>true</code> if this Value is a NUMBER.
*/
public boolean isNumber()
{
return this.type == ValueType.NUMBER;
}
/**
* Check if this Value is a STRING.
*
* @return <code>true</code> if this Value is a STRING.
*/
public boolean isString()
{
return this.type == ValueType.STRING;
}
/**
* Check if this Value is a MAP.
*
* @return <code>true</code> if this Value is a MAP.
*/
public boolean isMap()
{
return this.type == ValueType.MAP;
}
/**
* Check if this Value is a FUNCTION.
*
* @return <code>true</code> if this Value is a FUNCTION.
*/
public boolean isFunction()
{
return this.type == ValueType.FUNCTION;
}
/**
* Check if this Value is an OBJECT.
*
* @return <code>true</code> if this Value is an OBJECT.
*/
public boolean isObject()
{
return this.type == ValueType.OBJECT;
}
/**
* Gets this Value's NUMBER.
*
* @return The NUMBER of this Value.
*/
public double getNumber()
{
if (this.type != ValueType.NUMBER)
throw new WeelException("Value is not a NUMBER");
return this.number;
}
/**
* Gets this Value's STRING.
*
* @return The STRING of this Value.
*/
public String getString()
{
if (this.type != ValueType.STRING)
throw new WeelException("Value is not a STRING");
return (String)this.object;
}
/**
* Gets this Value's MAP.
*
* @return The MAP of this Value.
*/
public ValueMap getMap()
{
if (this.type != ValueType.MAP)
throw new WeelException("Value is not a MAP");
return (ValueMap)this.object;
}
/**
* Gets this Value's FUNCTION.
*
* @return The FUNCTION of this Value.
*/
public WeelFunction getFunction()
{
if (this.type != ValueType.FUNCTION)
throw new WeelException("Value is not a FUNCTION");
return (WeelFunction)this.object;
}
/**
* Gets this Value's OBJECT.
*
* @return The OBJECT of this Value.
*/
public Object getObject()
{
if (this.type != ValueType.OBJECT)
throw new WeelException("Value is not an OBJECT");
return this.object;
}
/**
* Returns the size of this value.
*
* @return The size as a double.
*/
public double size()
{
switch (this.type)
{
case NUMBER:
return Math.abs(this.number);
case STRING:
return ((String)this.object).length();
case MAP:
return ((ValueMap)this.object).size();
case FUNCTION:
return ((WeelFunction)this.object).arguments;
default:
return 0;
}
}
}