Package com.google.dart.engine.html.ast

Source Code of com.google.dart.engine.html.ast.XmlNode

/*
* Copyright (c) 2013, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html
*
* 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.dart.engine.html.ast;

import com.google.dart.engine.AnalysisEngine;
import com.google.dart.engine.element.Element;
import com.google.dart.engine.html.ast.visitor.ToSourceVisitor;
import com.google.dart.engine.html.ast.visitor.XmlVisitor;
import com.google.dart.engine.html.scanner.Token;
import com.google.dart.engine.utilities.dart.ParameterKind;
import com.google.dart.engine.utilities.io.PrintStringWriter;
import com.google.dart.engine.utilities.translation.DartOmit;
import com.google.dart.engine.utilities.translation.DartOptional;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
* The abstract class {@code XmlNode} defines behavior common to all XML/HTML nodes.
*
* @coverage dart.engine.html
*/
public abstract class XmlNode {
  /**
   * The parent of the node, or {@code null} if the node is the root of an AST structure.
   */
  private XmlNode parent;

  /**
   * The element associated with this node or {@code null} if the receiver is not resolved.
   */
  private Element element;

  /**
   * Use the given visitor to visit this node.
   *
   * @param visitor the visitor that will visit this node
   * @return the value returned by the visitor as a result of visiting this node
   */
  public abstract <R> R accept(XmlVisitor<R> visitor);

  /**
   * Return the first token included in this node's source range.
   *
   * @return the first token or {@code null} if none
   */
  public abstract Token getBeginToken();

  /**
   * Return the element associated with this node.
   *
   * @return the element or {@code null} if the receiver is not resolved
   */
  public Element getElement() {
    return element;
  }

  /**
   * Return the offset of the character immediately following the last character of this node's
   * source range. This is equivalent to {@code node.getOffset() + node.getLength()}. For an html
   * unit this will be equal to the length of the unit's source.
   *
   * @return the offset of the character just past the node's source range
   */
  public int getEnd() {
    return getOffset() + getLength();
  }

  /**
   * Return the last token included in this node's source range.
   *
   * @return the last token or {@code null} if none
   */
  public abstract Token getEndToken();

  /**
   * Return the number of characters in the node's source range.
   *
   * @return the number of characters in the node's source range
   */
  public int getLength() {
    Token beginToken = getBeginToken();
    Token endToken = getEndToken();
    if (beginToken == null || endToken == null) {
      return -1;
    }
    return endToken.getOffset() + endToken.getLength() - beginToken.getOffset();
  }

  /**
   * Return the offset from the beginning of the file to the first character in the node's source
   * range.
   *
   * @return the offset from the beginning of the file to the first character in the node's source
   *         range
   */
  public int getOffset() {
    Token beginToken = getBeginToken();
    if (beginToken == null) {
      return -1;
    }
    return getBeginToken().getOffset();
  }

  /**
   * Return this node's parent node, or {@code null} if this node is the root of an AST structure.
   * <p>
   * Note that the relationship between an AST node and its parent node may change over the lifetime
   * of a node.
   *
   * @return the parent of this node, or {@code null} if none
   */
  public XmlNode getParent() {
    return parent;
  }

  /**
   * Set the element associated with this node.
   *
   * @param element the element
   */
  public void setElement(Element element) {
    this.element = element;
  }

  @Override
  public String toString() {
    PrintStringWriter writer = new PrintStringWriter();
    accept(new ToSourceVisitor(writer));
    return writer.toString();
  }

  /**
   * Use the given visitor to visit all of the children of this node. The children will be visited
   * in source order.
   *
   * @param visitor the visitor that will be used to visit the children of this node
   */
  public abstract void visitChildren(XmlVisitor<?> visitor);

  /**
   * Make this node the parent of the given child node.
   *
   * @param child the node that will become a child of this node
   * @return the node that was made a child of this node
   */
  protected <T extends XmlNode> T becomeParentOf(T child) {
    if (child != null) {
      XmlNode node = child; // Java 7 access rules require a temp of a concrete type.
      node.setParent(this);
    }
    return child;
  }

  /**
   * Make this node the parent of the given child nodes.
   *
   * @param children the nodes that will become the children of this node
   * @return the nodes that were made children of this node
   */
  @DartOmit
  protected final <T extends XmlNode> List<T> becomeParentOfAll(List<T> children) {
    return becomeParentOfAll(children, null);
  }

  /**
   * Make this node the parent of the given child nodes.
   *
   * @param children the nodes that will become the children of this node
   * @param ifEmpty the (empty) nodes to return if "children" is empty
   * @return the nodes that were made children of this node
   */
  protected final <T extends XmlNode> List<T> becomeParentOfAll(List<T> children,
      @DartOptional(kind = ParameterKind.NAMED) List<T> ifEmpty) {
    if (children == null || children.isEmpty()) {
      if (ifEmpty != null) {
        return ifEmpty;
      }
    }
    if (children != null) {
      for (Iterator<T> iter = children.iterator(); iter.hasNext();) {
        XmlNode node = iter.next(); // Java 7 access rules require a temp of a concrete type.
        node.setParent(this);
      }
      // This will create ArrayList for exactly given number of elements.
      return new ArrayList<T>(children);
    }
    return children;
  }

  /**
   * This method exists for debugging purposes only.
   */
  private void appendIdentifier(StringBuilder builder, XmlNode node) {
    if (node instanceof XmlTagNode) {
      builder.append(((XmlTagNode) node).getTag());
    } else if (node instanceof XmlAttributeNode) {
      builder.append(((XmlAttributeNode) node).getName());
    } else {
      builder.append("htmlUnit");
    }
  }

  /**
   * This method exists for debugging purposes only.
   */
  private String buildRecursiveStructureMessage(XmlNode newParent) {
    StringBuilder builder = new StringBuilder();
    builder.append("Attempt to create recursive structure: ");
    XmlNode current = newParent;
    while (current != null) {
      if (current != newParent) {
        builder.append(" -> ");
      }
      if (current == this) {
        builder.append('*');
        appendIdentifier(builder, current);
        builder.append('*');
      } else {
        appendIdentifier(builder, current);
      }
      current = current.getParent();
    }
    return builder.toString();
  }

  /**
   * Set the parent of this node to the given node.
   *
   * @param newParent the node that is to be made the parent of this node
   */
  private void setParent(XmlNode newParent) {
    XmlNode current = newParent;
    while (current != null) {
      if (current == this) {
        AnalysisEngine.getInstance().getLogger().logError(
            "Circular structure while setting an XML node's parent",
            new IllegalArgumentException(buildRecursiveStructureMessage(newParent)));
        return;
      }
      current = current.getParent();
    }
    parent = newParent;
  }
}
TOP

Related Classes of com.google.dart.engine.html.ast.XmlNode

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.