use of com.google.template.soy.types.SanitizedType in project closure-templates by google.
the class SoyExpression method unboxAs.
// TODO(lukes): split this into a set of specialized methods, one per target type like we did
// for the 'coerce' methods.
/**
* Unboxes this to a {@link SoyExpression} with a runtime type of {@code asType}.
*
* <p>This method is appropriate when you know (likely via inspection of the {@link #soyType()},
* or other means) that the value does have the appropriate type but you prefer to interact with
* it as its unboxed representation. If you simply want to 'coerce' the given value to a new type
* consider {@link #coerceToBoolean()} {@link #coerceToDouble()} or {@link #coerceToString()}
* which are designed for that use case.
*/
public SoyExpression unboxAs(Class<?> asType) {
checkArgument(!SoyValue.class.isAssignableFrom(asType), "Cannot use unboxAs() to convert to a SoyValue: %s, use .box() instead", asType);
// SoyExpressions that are already unboxed fall into this case.
if (BytecodeUtils.isDefinitelyAssignableFrom(Type.getType(asType), soyRuntimeType.runtimeType())) {
return this;
}
// Attempting to unbox an unboxed proto
if (asType.equals(Message.class) && soyRuntimeType.isKnownProto() && !isBoxed()) {
return this;
}
if (!isBoxed()) {
throw new IllegalStateException("Trying to unbox an unboxed value (" + soyRuntimeType + ") into " + asType + " doesn't make sense. Should you be using a type coercion? e.g. coerceToBoolean()");
}
if (asType.equals(boolean.class)) {
return forBool(delegate.invoke(MethodRef.SOY_VALUE_BOOLEAN_VALUE));
}
if (asType.equals(long.class)) {
return forInt(delegate.invoke(MethodRef.SOY_VALUE_LONG_VALUE));
}
if (asType.equals(double.class)) {
return forFloat(delegate.invoke(MethodRef.SOY_VALUE_FLOAT_VALUE));
}
if (delegate.isNonNullable()) {
if (asType.equals(String.class)) {
Expression unboxedString = delegate.invoke(MethodRef.SOY_VALUE_STRING_VALUE);
// We need to ensure that santized types don't lose their content kinds
return soyRuntimeType.isKnownSanitizedContent() ? forSanitizedString(unboxedString, ((SanitizedType) soyType()).getContentKind()) : forString(unboxedString);
}
if (asType.equals(List.class)) {
return unboxAsList();
}
if (asType.equals(Message.class)) {
SoyRuntimeType runtimeType = getUnboxedType(soyType());
return forProto(runtimeType, delegate.invoke(MethodRef.SOY_PROTO_VALUE_GET_PROTO).checkedCast(runtimeType.runtimeType()));
}
} else {
// else it must be a List/Proto/String all of which must preserve null through the unboxing
// operation
// TODO(lukes): this violates the expression contract since we jump to a label outside the
// scope of the expression
final Label end = new Label();
Expression nonNullDelegate = new Expression(resultType(), features()) {
@Override
protected void doGen(CodeBuilder adapter) {
delegate.gen(adapter);
BytecodeUtils.nullCoalesce(adapter, end);
}
};
return withSource(nonNullDelegate).asNonNullable().unboxAs(asType).asNullable().labelEnd(end);
}
throw new UnsupportedOperationException("Can't unbox " + soyRuntimeType + " as " + asType);
}
Aggregations