com.tangosol.config.expression.Value Maven / Gradle / Ivy
Show all versions of coherence Show documentation
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.config.expression;
import com.oracle.coherence.common.base.Converter;
import com.tangosol.run.xml.XmlValue;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.UnknownFormatConversionException;
/**
* A {@link Value} is an immutable object that represents a value whose type is unknown at compile time.
* That is, the type of the value will only be known at runtime when it's requested.
*
* Much like a Variant
* (wikipedia) a {@link Value} permits runtime coercion into other types, as and when required.
*
* @author bo 2011.06.05
* @since Coherence 12.1.2
*/
@SuppressWarnings("rawtypes")
public final class Value
{
// ----- constructors ---------------------------------------------------
/**
* Construct a null
{@link Value}.
*/
public Value()
{
m_oValue = null;
}
/**
* Construct an {@link Object}-based {@link Value}.
*
* @param oValue the value of the {@link Value} instance
*/
public Value(Object oValue)
{
m_oValue = oValue;
}
/**
* Construct a {@link String}-based {@link Value}.
*
* Note: The provided {@link String} is trimmed for leading and trailing white-space.
*
* @param sValue the value of the {@link Value} instance
*/
public Value(String sValue)
{
m_oValue = sValue == null ? null : sValue.trim();
}
/**
* Construct a {@link Value}-based on another {@link Value}.
*
* @param value the value for the resulting {@link Value} instance
*/
public Value(Value value)
{
m_oValue = value.m_oValue;
}
/**
* Construct a {@link Value} based on the string content of an {@link XmlValue}.
*
* Note:
*
* - The {@link XmlValue} content is used and not the xml itself.
*
- The content will be trimmed for leading and trailing white-space.
*
*
* @param value the value of the {@link Value} instance
*/
public Value(XmlValue value)
{
m_oValue = value == null ? null : value.getString().trim();
}
/**
* Determines if the {@link Value} represents a null
value.
*
* @return true
if the value of the {@link Value} is null
, otherwise false
*/
public boolean isNull()
{
return m_oValue == null;
}
/**
* Obtains the underlying {@link Object} representation of the {@link Value}.
*
* @return The {@link Object} representation of the {@link Value} (may be null
)
*/
public Object get()
{
return m_oValue;
}
/**
* Determines if the {@link Value} supports conversion/coercion to the specified type.
*
* NOTE: This does not test whether the {@link Value} can be coerced without an exception.
*
* @param clzType the type to which the {@link Value} should be coerced
*
* @return true
if type is coercable, false
otherwise
*/
public boolean supports(Class> clzType)
{
// determine if we can convert the value to the type
boolean fSupported = clzType.isEnum() || clzType.isAssignableFrom(m_oValue.getClass())
|| clzType.isAssignableFrom(this.getClass())
|| s_mapTypeConvertersByClass.containsKey(clzType);
if (!fSupported && m_oValue != null)
{
// determine if we can construct an instance of the type with the value or using a string
try
{
fSupported = clzType.getConstructor(m_oValue.getClass()) != null;
}
catch (Exception e)
{
try
{
fSupported = clzType.getConstructor(String.class) != null;
}
catch (Exception e1)
{
fSupported = false;
}
}
}
return fSupported;
}
/**
* Attempts to return the value of the {@link Value} coerced to a specified type.
*
* @param the expected type of the value
* @param clzType the expected type of the value (the value to coerce to)
*
* @return the {@link Value} coerced in the required type
*
* @throws ClassCastException If the value of the {@link Value} can't be coerced to the specified type
* @throws NumberFormatException If the value of the {@link Value} can't be coerced to the specified type
* @throws UnknownFormatConversionException If the value of the {@link Value} can't be coerced to the specified type
*/
@SuppressWarnings("unchecked")
public T as(Class clzType)
throws ClassCastException, UnknownFormatConversionException, NumberFormatException
{
if (isNull())
{
return null;
}
else if (clzType.isInstance(m_oValue))
{
return (T) m_oValue;
}
else if (clzType.isAssignableFrom(this.getClass()))
{
return (T) this;
}
else if (clzType.isEnum())
{
// determine the value as a string
String sValue = m_oValue.toString();
try
{
return (T) Enum.valueOf((Class) clzType, sValue);
}
catch (Exception exception)
{
// the enum is unknown/unsupported
throw new ClassCastException(String.format("The specified Enum value '%s' is unknown.", sValue));
}
}
else
{
// attempt to use a predefined converter
Converter