/*
* Copyright 2009 Google Inc.
*
* 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.google.template.soy.data.internalutils;
import com.google.common.collect.ImmutableMap;
import com.google.template.soy.base.SourceLocation;
import com.google.template.soy.base.SoySyntaxException;
import com.google.template.soy.base.internal.LegacyInternalSyntaxException;
import com.google.template.soy.data.SoyDataException;
import com.google.template.soy.data.SoyValue;
import com.google.template.soy.data.SoyValueConverter;
import com.google.template.soy.data.restricted.BooleanData;
import com.google.template.soy.data.restricted.FloatData;
import com.google.template.soy.data.restricted.IntegerData;
import com.google.template.soy.data.restricted.NullData;
import com.google.template.soy.data.restricted.PrimitiveData;
import com.google.template.soy.data.restricted.StringData;
import com.google.template.soy.exprtree.BooleanNode;
import com.google.template.soy.exprtree.ExprNode.PrimitiveNode;
import com.google.template.soy.exprtree.FloatNode;
import com.google.template.soy.exprtree.IntegerNode;
import com.google.template.soy.exprtree.NullNode;
import com.google.template.soy.exprtree.StringNode;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Internal utilities related to Soy values.
*
* <p>Important: Do not use outside of Soy code (treat as superpackage-private).
*
*/
public class InternalValueUtils {
private InternalValueUtils() {}
/**
* Converts a primitive data object into a primitive expression node.
*
* @param primitiveData The primitive data object to convert. Must not be undefined.
* @return The resulting primitive expression node.
*/
@Nullable
public static PrimitiveNode convertPrimitiveDataToExpr(PrimitiveData primitiveData) {
if (primitiveData instanceof StringData) {
return new StringNode(primitiveData.stringValue(), SourceLocation.UNKNOWN);
} else if (primitiveData instanceof BooleanData) {
return new BooleanNode(primitiveData.booleanValue(), SourceLocation.UNKNOWN);
} else if (primitiveData instanceof IntegerData) {
// NOTE: We only support numbers in the range of JS [MIN_SAFE_INTEGER, MAX_SAFE_INTEGER]
if (!IntegerNode.isInRange(primitiveData.longValue())) {
return null;
} else {
return new IntegerNode(primitiveData.longValue(), SourceLocation.UNKNOWN);
}
} else if (primitiveData instanceof FloatData) {
return new FloatNode(primitiveData.floatValue(), SourceLocation.UNKNOWN);
} else if (primitiveData instanceof NullData) {
return new NullNode(SourceLocation.UNKNOWN);
} else {
throw new IllegalArgumentException();
}
}
/**
* Converts a primitive expression node into a primitive data object.
*
* @param primitiveNode The primitive expression node to convert.
* @return The resulting primitive data object.
*/
public static PrimitiveData convertPrimitiveExprToData(PrimitiveNode primitiveNode) {
if (primitiveNode instanceof StringNode) {
return StringData.forValue(((StringNode) primitiveNode).getValue());
} else if (primitiveNode instanceof BooleanNode) {
return BooleanData.forValue(((BooleanNode) primitiveNode).getValue());
} else if (primitiveNode instanceof IntegerNode) {
return IntegerData.forValue(((IntegerNode) primitiveNode).getValue());
} else if (primitiveNode instanceof FloatNode) {
return FloatData.forValue(((FloatNode) primitiveNode).getValue());
} else if (primitiveNode instanceof NullNode) {
return NullData.INSTANCE;
} else {
throw new IllegalArgumentException();
}
}
/**
* Converts a compile-time globals map in user-provided format into one in the internal format.
*
* <p>The returned map will have the same iteration order as the provided map.
*
* @param compileTimeGlobalsMap Map from compile-time global name to value. The values can be any
* of the Soy primitive types: null, boolean, integer, float (Java double), or string.
* @return An equivalent map in the internal format.
* @throws SoySyntaxException If the map contains an invalid value.
*/
public static ImmutableMap<String, PrimitiveData> convertCompileTimeGlobalsMap(
Map<String, ?> compileTimeGlobalsMap) {
ImmutableMap.Builder<String, PrimitiveData> resultMapBuilder = ImmutableMap.builder();
for (Map.Entry<String, ?> entry : compileTimeGlobalsMap.entrySet()) {
Object valueObj = entry.getValue();
PrimitiveData value;
boolean isValidValue = true;
try {
SoyValue value0 = SoyValueConverter.UNCUSTOMIZED_INSTANCE.convert(valueObj).resolve();
if (!(value0 instanceof PrimitiveData)) {
isValidValue = false;
}
value = (PrimitiveData) value0;
} catch (SoyDataException sde) {
isValidValue = false;
value = null; // make compiler happy
}
if (!isValidValue) {
throw LegacyInternalSyntaxException.createWithoutMetaInfo(
"Compile-time globals map contains invalid value: " + valueObj + ".");
}
resultMapBuilder.put(entry.getKey(), value);
}
return resultMapBuilder.build();
}
}