Package com.google.template.soy.soytree

Source Code of com.google.template.soy.soytree.TemplateBasicNode$CommandTextInfo

/*
* Copyright 2011 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.base.Preconditions;
import com.google.template.soy.base.BaseUtils;
import com.google.template.soy.base.SoySyntaxException;
import com.google.template.soy.data.SanitizedContent.ContentKind;
import com.google.template.soy.data.internalutils.NodeContentKinds;
import com.google.template.soy.soytree.CommandTextAttributesParser.Attribute;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;


/**
* Node representing a basic template.
*
* <p> Important: Do not use outside of Soy code (treat as superpackage-private).
*
* @author Kai Huang
*/
public class TemplateBasicNode extends TemplateNode {


  /**
   * Private helper class used by constructors. Encapsulates all the info derived from the command
   * text.
   */
  @Immutable
  private static class CommandTextInfo extends TemplateNode.CommandTextInfo {

    public final boolean isOverride;

    public CommandTextInfo(
        String commandText, String templateName, @Nullable String partialTemplateName,
        boolean isOverride, boolean isPrivate, AutoescapeMode autoescapeMode,
        ContentKind contentKind, SyntaxVersion syntaxVersion) {
      super(commandText, templateName, partialTemplateName, isPrivate, autoescapeMode,
          contentKind, syntaxVersion);
      this.isOverride = isOverride;
    }
  }


  /** Pattern for a template name not listed as an attribute name="...". */
  private static final Pattern NONATTRIBUTE_TEMPLATE_NAME =
      Pattern.compile("^ (?! name=\") [.\\w]+ (?= \\s | $)", Pattern.COMMENTS);

  /** Parser for the command text. */
  private static final CommandTextAttributesParser ATTRIBUTES_PARSER =
      new CommandTextAttributesParser("template",
          new Attribute("name", Attribute.ALLOW_ALL_VALUES, null),
          new Attribute("private", Attribute.BOOLEAN_VALUES, "false"),
          new Attribute("override", Attribute.BOOLEAN_VALUES, null)// V1
          new Attribute("autoescape", AutoescapeMode.getAttributeValues(), null),
          new Attribute("kind", NodeContentKinds.getAttributeValues(), null));


  /** Whether this template overrides another (always false for syntax version V2). */
  private final boolean isOverride;


  /**
   * Creates a TemplateNode given the source command text.
   * @param id The id for this node.
   * @param soyFileHeaderInfo Info from the containing Soy file's header declarations.
   * @param commandText The command text.
   * @param soyDoc The full SoyDoc, including the start/end tokens, or null if the template is not
   *     preceded by SoyDoc.
   * @throws SoySyntaxException If a syntax error is found.
   */
  public TemplateBasicNode(
      int id, SoyFileHeaderInfo soyFileHeaderInfo, String commandText, @Nullable String soyDoc)
      throws SoySyntaxException {
    this(id, soyFileHeaderInfo, parseCommandTextHelper(soyFileHeaderInfo, commandText), soyDoc);
  }


  /**
   * Private helper for constructor
   * {@link #TemplateBasicNode(int, SoyFileHeaderInfo, String, String)}.
   */
  private static final CommandTextInfo parseCommandTextHelper(
      SoyFileHeaderInfo soyFileHeaderInfo, String commandText) {

    SyntaxVersion syntaxVersion = SyntaxVersion.V2;

    String commandTextForParsing = commandText;

    // Handle template name not listed as an attribute name="...".
    String nameAttr = null;
    Matcher ntnMatcher = NONATTRIBUTE_TEMPLATE_NAME.matcher(commandTextForParsing);
    if (ntnMatcher.find()) {
      nameAttr = ntnMatcher.group();
      commandTextForParsing = commandTextForParsing.substring(ntnMatcher.end()).trim();
    }

    Map<String, String> attributes = ATTRIBUTES_PARSER.parse(commandTextForParsing);

    if (nameAttr == null) {
      nameAttr = attributes.get("name");
      if (nameAttr == null) {
        throw SoySyntaxException.createWithoutMetaInfo(
            "Invalid 'template' command missing template name: {template " + commandText + "}.");
      }
    } else {
      if (attributes.get("name") != null) {
        throw SoySyntaxException.createWithoutMetaInfo(
            "Invalid 'template' command with template name declared multiple times (" +
            nameAttr + ", " + attributes.get("name") + ").");
      }
    }
    String templateName;
    String partialTemplateName;
    if (BaseUtils.isIdentifierWithLeadingDot(nameAttr)) {
      if (soyFileHeaderInfo.namespace == null) {
        throw SoySyntaxException.createWithoutMetaInfo(
            "Missing namespace in Soy file containing 'template' with namespace-relative name" +
                " ({template " + commandText + "}).");
      }
      partialTemplateName = nameAttr;
      templateName = soyFileHeaderInfo.namespace + partialTemplateName;
    } else if (BaseUtils.isDottedIdentifier(nameAttr)) {
      syntaxVersion = SyntaxVersion.V1;
      templateName = nameAttr;
      partialTemplateName = null;
    } else {
      throw SoySyntaxException.createWithoutMetaInfo("Invalid template name \"" + nameAttr + "\".");
    }

    boolean isPrivate = attributes.get("private").equals("true");

    boolean isOverride;
    String overrideAttr = attributes.get("override");
    if (overrideAttr == null) {
      isOverride = false;
    } else {
      syntaxVersion = SyntaxVersion.V1;
      isOverride = overrideAttr.equals("true");
    }

    AutoescapeMode autoescapeMode;
    String autoescapeModeStr = attributes.get("autoescape");
    if (autoescapeModeStr != null) {
      autoescapeMode = AutoescapeMode.forAttributeValue(autoescapeModeStr);
    } else {
      autoescapeMode = soyFileHeaderInfo.defaultAutoescapeMode;  // Inherit from containing file.
    }

    ContentKind contentKind = (attributes.get("kind") != null) ?
        NodeContentKinds.forAttributeValue(attributes.get("kind")) : null;

    return new CommandTextInfo(
        commandText, templateName, partialTemplateName, isOverride, isPrivate, autoescapeMode,
        contentKind, syntaxVersion);
  }


  /**
   * Creates a TemplateNode given values for fields.
   * @param soyFileHeaderInfo Info from the containing Soy file's header declarations.
   * @param templateName The full template name.
   * @param partialTemplateName The template name without any namespace, or null for templates in
   *     V1 syntax.
   * @param useAttrStyleForName true to use an attribute to specify the name.
   *     This is purely cosmetic.
   * @param isOverride True iff the template overrides another (false for V2).
   * @param isPrivate True iff the template can only be used by other templates from the same file
   * @param autoescapeMode Specifies how <code>{print}</code> commands are escaped.
   */
  public TemplateBasicNode(
      int id, SoyFileHeaderInfo soyFileHeaderInfo, String templateName,
      @Nullable String partialTemplateName, boolean useAttrStyleForName, boolean isOverride,
      boolean isPrivate, AutoescapeMode autoescapeMode, ContentKind contentKind,
      @Nullable String soyDoc, SyntaxVersion syntaxVersion) {
    this(
        id, soyFileHeaderInfo,
        buildCommandTextInfoHelper(
            templateName, partialTemplateName, useAttrStyleForName, isOverride, isPrivate,
            autoescapeMode, contentKind, syntaxVersion),
        soyDoc);
  }


  /**
   * Private helper for constructor
   * {@link #TemplateBasicNode(
   *     int, SoyFileHeaderInfo, String, String, boolean, boolean, boolean, AutoescapeMode,
   *     ContentKind, String, SyntaxVersion)}.
   */
  private static final CommandTextInfo buildCommandTextInfoHelper(
      String templateName, @Nullable String partialTemplateName, boolean useAttrStyleForName,
      boolean isOverride, boolean isPrivate, AutoescapeMode autoescapeMode, ContentKind contentKind,
      SyntaxVersion syntaxVersion) {

    Preconditions.checkArgument(BaseUtils.isDottedIdentifier(templateName));
    Preconditions.checkArgument(
        partialTemplateName == null || BaseUtils.isIdentifierWithLeadingDot(partialTemplateName));
    Preconditions.checkArgument((contentKind != null) == (autoescapeMode == AutoescapeMode.STRICT));

    StringBuilder commandText = new StringBuilder();
    String templateNameInCommandText =
        (partialTemplateName != null) ? partialTemplateName : templateName;
    if (useAttrStyleForName) {
      commandText.append("name=\"").append(templateNameInCommandText).append('"');
    } else {
      commandText.append(templateNameInCommandText);
    }
    commandText.append(" autoescape=\"").append(autoescapeMode.getAttributeValue()).append('"');
    if (contentKind != null) {
      commandText.append(" kind=\"" + NodeContentKinds.toAttributeValue(contentKind) + '"');
    }
    if (isOverride) {
      commandText.append(" override=\"true\"");
    }
    if (isPrivate) {
      commandText.append(" private=\"true\"");
    }

    return new CommandTextInfo(
        commandText.toString(), templateName, partialTemplateName, isOverride, isPrivate,
        autoescapeMode, contentKind, syntaxVersion);
  }


  /**
   * Private helper constructor used by both of the constructors
   * {@link #TemplateBasicNode(int, SoyFileHeaderInfo, String, String)} and
   * {@link #TemplateBasicNode(
   *     int, SoyFileHeaderInfo, String, String, boolean, boolean, boolean, AutoescapeMode,
   *     ContentKind, String, SyntaxVersion)}.
   */
  private TemplateBasicNode(
      int id, SoyFileHeaderInfo soyFileHeaderInfo, CommandTextInfo commandTextInfo,
      @Nullable String soyDoc) {
    super(id, soyFileHeaderInfo, "template", commandTextInfo, soyDoc);
    this.isOverride = commandTextInfo.isOverride;
  }


  /**
   * Copy constructor.
   * @param orig The node to copy.
   */
  protected TemplateBasicNode(TemplateBasicNode orig) {
    super(orig);
    this.isOverride = orig.isOverride;
  }


  @Override public Kind getKind() {
    return Kind.TEMPLATE_BASIC_NODE;
  }


  @Override public String getTemplateNameForUserMsgs() {
    return getTemplateName();
  }


  /** Returns whether this template overrides another (always false for syntax version V2). */
  public boolean isOverride() {
    return isOverride;
  }


  @Override public TemplateBasicNode clone() {
    return new TemplateBasicNode(this);
  }

}
TOP

Related Classes of com.google.template.soy.soytree.TemplateBasicNode$CommandTextInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.