/**
   * Applies the built up transforms, changing {@link RawTextNode}s to the corresponding Html*Nodes,
   * if any. If a node itself does not correspond to any new nodes, it is simply removed.
   */
  private void applyTransforms() {
    for (RawTextNode node : visitedRawTextNodes) {
      ParentSoyNode<StandaloneNode> parent = node.getParent();

      parent.addChildren(parent.getChildIndex(node), transformMapping.get(node));
      parent.removeChild(node);
    }
  }
 /**
  * Derives a {@link SourceLocation} from the given {@link RawTextNode}, for text the length of
  * charSequence ending at endOffset.
  */
 private SourceLocation deriveSourceLocation(RawTextNode node) {
   // TODO(sparhami) Since the parser strips templates and combines whitespace, including newlines
   // we can't find the correct source location based on where we are in the RawTextNode. The
   // parser needs to be modified to not strip whitespace and to not combine text before and after
   // comments. Doing the former is difficult due to commands like {\n}.
   return node.getSourceLocation();
 }
  public void testWithoutCssRenamingMap() {

    TemplateNode template =
        (TemplateNode) SharedTestUtils.getNode(SharedTestUtils.parseSoyFiles(TEST_FILE_CONTENT));

    // Before.
    assertEquals(9, template.numChildren());
    CssNode cn1 = (CssNode) template.getChild(1);
    assertEquals("AAA", cn1.getSelectorText());
    CssNode cn7 = (CssNode) template.getChild(7);
    assertEquals("$goo", cn7.getComponentNameText());
    assertEquals("BBB", cn7.getSelectorText());

    (new RenameCssVisitor(null)).exec(template);
    (new CombineConsecutiveRawTextNodesVisitor()).exec(template);

    // After.
    assertEquals(5, template.numChildren());
    RawTextNode rtn0 = (RawTextNode) template.getChild(0);
    assertEquals("<div class=\"AAA ", rtn0.getRawText());
    PrintNode pn1 = (PrintNode) template.getChild(1);
    assertEquals("$goo", pn1.getExprText());
    RawTextNode rtn2 = (RawTextNode) template.getChild(2);
    assertEquals("-AAA BBB ", rtn2.getRawText());
    PrintNode pn3 = (PrintNode) template.getChild(3);
    assertEquals("$goo", pn3.getExprText());
    RawTextNode rtn4 = (RawTextNode) template.getChild(4);
    assertEquals("-BBB\">", rtn4.getRawText());
  }
  /**
   * Visits a {@link RawTextNode}, going through each of the characters and building up the HTML
   * pieces (e.g. {@link HtmlOpenTagStartNode} and {@link HtmlOpenTagEndNode}). The new pieces are
   * mapped to the {@link RawTextNode} where they ended. The {@link #applyTransforms()} method
   * actually performs the replacement.
   */
  @Override
  protected void visitRawTextNode(RawTextNode node) {
    String content = node.getRawText();

    // Mark all visited RawTextNodes for removal. A single RawTextNode may not map to any Html*Nodes
    // by itself, but we still want to remove it.
    visitedRawTextNodes.add(node);

    for (int i = 0; i < content.length(); i += 1) {
      consumeCharacter(node, content.charAt(i));
    }

    switch (getState()) {
      case TAG_NAME:
        /*
         * Force the end of a tag in the case we have something like:
         * <div{if $foo}...{/if} ...>
         */
        consumeCharacter(node, ' ');
        break;
      case PCDATA:
        createTextNode(node);
        break;
      case ATTR_VALUE:
        /*
         * Reached the end of a RawTextNode with some text, for example from:
         *
         *   <div foo="bar {if $condition}...{/if}">
         *
         * Take the text up until the end of the RawTextNode, "bar ", and add it to the attribute
         * values.
         */
        createAttributeValueNode(node);
        break;
      default:
        break;
    }
  }
  public void testWithCssRenamingMap() {

    TemplateNode template =
        (TemplateNode) SharedTestUtils.getNode(SharedTestUtils.parseSoyFiles(TEST_FILE_CONTENT));

    // Before.
    assertEquals(9, template.numChildren());
    CssNode cn1 = (CssNode) template.getChild(1);
    assertEquals("AAA", cn1.getSelectorText());
    CssNode cn7 = (CssNode) template.getChild(7);
    assertEquals("$goo", cn7.getComponentNameText());
    assertEquals("BBB", cn7.getSelectorText());

    // Use a CSS renaming map that only renames 'AAA'.
    SoyCssRenamingMap cssRenamingMap =
        new SoyCssRenamingMap() {
          @Override
          public String get(String key) {
            return key.equals("AAA") ? "XXX" : null;
          }
        };

    (new RenameCssVisitor(cssRenamingMap)).exec(template);
    (new CombineConsecutiveRawTextNodesVisitor()).exec(template);

    // After.
    assertEquals(5, template.numChildren());
    RawTextNode rtn0 = (RawTextNode) template.getChild(0);
    assertEquals("<div class=\"XXX ", rtn0.getRawText());
    PrintNode pn1 = (PrintNode) template.getChild(1);
    assertEquals("$goo", pn1.getExprText());
    RawTextNode rtn2 = (RawTextNode) template.getChild(2);
    assertEquals("-XXX BBB ", rtn2.getRawText());
    PrintNode pn3 = (PrintNode) template.getChild(3);
    assertEquals("$goo", pn3.getExprText());
    RawTextNode rtn4 = (RawTextNode) template.getChild(4);
    assertEquals("-BBB\">", rtn4.getRawText());
  }