/*
* Copyright 2010 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.soytree;
import com.google.common.collect.ImmutableList;
import com.google.template.soy.base.SourceLocation;
import com.google.template.soy.basetree.CopyState;
import com.google.template.soy.exprparse.ExpressionParser;
import com.google.template.soy.exprparse.SoyParsingContext;
import com.google.template.soy.exprtree.ExprNode;
import com.google.template.soy.exprtree.ExprRootNode;
import com.google.template.soy.soytree.SoyNode.ExprHolderNode;
import com.google.template.soy.soytree.SoyNode.MsgSubstUnitNode;
import com.google.template.soy.soytree.SoyNode.SplitLevelTopNode;
import javax.annotation.Nullable;
/**
* Node representing a 'select' block.
*
* <p>Important: Do not use outside of Soy code (treat as superpackage-private).
*
*/
public final class MsgSelectNode extends AbstractParentCommandNode<CaseOrDefaultNode>
implements MsgSubstUnitNode, SplitLevelTopNode<CaseOrDefaultNode>, ExprHolderNode {
/** Fallback base select var name. */
public static final String FALLBACK_BASE_SELECT_VAR_NAME = "STATUS";
/** The expression for the value to select on. */
private final ExprRootNode selectExpr;
/** The base select var name (what the translator sees). */
private final String baseSelectVarName;
private MsgSelectNode(
int id, String commandText, ExprRootNode selectExpr, SourceLocation sourceLocation) {
super(id, sourceLocation, "select", commandText);
this.selectExpr = selectExpr;
// TODO: Maybe allow user to write 'phname' attribute in 'select' tag.
// Note: If we do add support for 'phname' for 'select', it would also be a good time to clean
// up how 'phname' is parsed for 'call'. Right now, it's parsed in TemplateParser.jj because
// 'print' needs it to be parsed in TemplateParser.jj (due to print directives possibly
// appearing between the expression and the 'phname' attribute). But for 'call', it should
// really be parsed in CallNode.
baseSelectVarName =
MsgSubstUnitBaseVarNameUtils.genNaiveBaseNameForExpr(
selectExpr.getRoot(), FALLBACK_BASE_SELECT_VAR_NAME);
}
/**
* @param id The id for this node.
* @param sourceLocation The node's source location.
* @param selectExpr The expression for the value to select on.
* @param baseSelectVarName The base select var name to use (what the translator sees), or null if
* it should be generated from the select expression.
*/
public MsgSelectNode(
int id,
SourceLocation sourceLocation,
ExprRootNode selectExpr,
@Nullable String baseSelectVarName) {
super(
id,
sourceLocation,
"select",
selectExpr.toSourceString()
+ ((baseSelectVarName != null) ? " phname=\"" + baseSelectVarName + "\"" : ""));
this.selectExpr = selectExpr;
this.baseSelectVarName =
(baseSelectVarName != null)
? baseSelectVarName
: MsgSubstUnitBaseVarNameUtils.genNaiveBaseNameForExpr(
selectExpr.getRoot(), FALLBACK_BASE_SELECT_VAR_NAME);
}
/**
* Copy constructor.
*
* @param orig The node to copy.
*/
private MsgSelectNode(MsgSelectNode orig, CopyState copyState) {
super(orig, copyState);
this.selectExpr = orig.selectExpr.copy(copyState);
this.baseSelectVarName = orig.baseSelectVarName;
}
@Override
public Kind getKind() {
return Kind.MSG_SELECT_NODE;
}
/** Returns the expression for the value to select on. */
public ExprRootNode getExpr() {
return selectExpr;
}
/** Returns the base select var name (what the translator sees). */
@Override
public String getBaseVarName() {
return baseSelectVarName;
}
@Override
public boolean shouldUseSameVarNameAs(MsgSubstUnitNode other) {
return (other instanceof MsgSelectNode)
&& this.getCommandText().equals(((MsgSelectNode) other).getCommandText());
}
@Override
public ImmutableList<ExprRootNode> getExprList() {
return ImmutableList.of(selectExpr);
}
@Override
public MsgBlockNode getParent() {
return (MsgBlockNode) super.getParent();
}
@Override
public MsgSelectNode copy(CopyState copyState) {
return new MsgSelectNode(this, copyState);
}
/** Builder for {@link MsgSelectNode}. */
public static final class Builder {
private final int id;
private final String commandText;
private final SourceLocation sourceLocation;
/**
* @param id The node's id.
* @param commandText The node's command text.
* @param sourceLocation The node's source location.
*/
public Builder(int id, String commandText, SourceLocation sourceLocation) {
this.id = id;
this.commandText = commandText;
this.sourceLocation = sourceLocation;
}
/**
* Returns a new {@link MsgSelectNode} built from this builder's state, reporting syntax errors
* to the given {@link ErrorReporter}.
*/
public MsgSelectNode build(SoyParsingContext context) {
ExprNode selectExpr =
new ExpressionParser(commandText, sourceLocation, context).parseExpression();
return new MsgSelectNode(id, commandText, new ExprRootNode(selectExpr), sourceLocation);
}
}
}