final void setNestedBlock(TemplateElement nestedBlock) {
   if (nestedBlock != null) {
     nestedBlock.parent = this;
     nestedBlock.index = 0;
   }
   this.nestedBlock = nestedBlock;
 }
 private TemplateElement getLastLeaf() {
   TemplateElement te = this;
   while (!te.isLeaf() && !(te instanceof Macro) && !(te instanceof BlockAssignment)) {
     // A macro or macro invocation is treated as a leaf here for special reasons
     te = te.getLastChild();
   }
   return te;
 }
 TemplateElement prevTerminalNode() {
   TemplateElement prev = previousSibling();
   if (prev != null) {
     return prev.getLastLeaf();
   } else if (parent != null) {
     return parent.prevTerminalNode();
   }
   return null;
 }
 TemplateElement nextTerminalNode() {
   TemplateElement next = nextSibling();
   if (next != null) {
     return next.getFirstLeaf();
   } else if (parent != null) {
     return parent.nextTerminalNode();
   }
   return null;
 }
 /** Used for some backward compatibility hacks. */
 MixedContent asMixedContent() {
   MixedContent mixedContent = new MixedContent();
   if (count != 0) {
     TemplateElement first = buffer[0];
     mixedContent.setChildren(this);
     mixedContent.setLocation(first.getTemplate(), first, getLast());
   }
   return mixedContent;
 }
 private static void insertDebugBreak(Template t, Breakpoint breakpoint) {
   TemplateElement te = findTemplateElement(t.getRootTreeNode(), breakpoint.getLine());
   if (te == null) {
     return;
   }
   TemplateElement parent = (TemplateElement) te.getParent();
   DebugBreak db = new DebugBreak(te);
   // TODO: Ensure there always is a parent by making sure
   // that the root element in the template is always a MixedContent
   // Also make sure it doesn't conflict with anyone's code.
   parent.setChildAt(parent.getIndex(te), db);
 }
 private void removeDebugBreaks(TemplateElement te) {
   int count = te.getChildCount();
   for (int i = 0; i < count; ++i) {
     TemplateElement child = (TemplateElement) te.getChildAt(i);
     while (child instanceof DebugBreak) {
       TemplateElement dbchild = (TemplateElement) child.getChildAt(0);
       te.setChildAt(i, dbchild);
       child = dbchild;
     }
     removeDebugBreaks(child);
   }
 }
 /** Used for some backward compatibility hacks. */
 TemplateElement asSingleElement() {
   if (count == 0) {
     return new TextBlock(CollectionUtils.EMPTY_CHAR_ARRAY, false);
   } else {
     TemplateElement first = buffer[0];
     if (count == 1) {
       return first;
     } else {
       MixedContent mixedContent = new MixedContent();
       mixedContent.setChildren(this);
       mixedContent.setLocation(first.getTemplate(), first, getLast());
       return mixedContent;
     }
   }
 }
 /**
  * @return an array of the {@link TemplateElement}s containing the given column and line numbers.
  */
 List<TemplateElement> containingElements(int column, int line) {
   final ArrayList<TemplateElement> elements = new ArrayList<TemplateElement>();
   TemplateElement element = rootElement;
   mainloop:
   while (element.contains(column, line)) {
     elements.add(element);
     for (Enumeration enumeration = element.children(); enumeration.hasMoreElements(); ) {
       TemplateElement elem = (TemplateElement) enumeration.nextElement();
       if (elem.contains(column, line)) {
         element = elem;
         continue mainloop;
       }
     }
     break;
   }
   return elements.isEmpty() ? null : elements;
 }
 public int getChildCount() {
   if (nestedBlock instanceof MixedContent) {
     return nestedBlock.getChildCount();
   }
   if (nestedBlock != null) {
     return 1;
   }
   return regulatedChildCount;
 }
 private void removeDebugBreak(Template t, Breakpoint breakpoint) {
   TemplateElement te = findTemplateElement(t.getRootTreeNode(), breakpoint.getLine());
   if (te == null) {
     return;
   }
   DebugBreak db = null;
   while (te != null) {
     if (te instanceof DebugBreak) {
       db = (DebugBreak) te;
       break;
     }
     te = (TemplateElement) te.getParent();
   }
   if (db == null) {
     return;
   }
   TemplateElement parent = (TemplateElement) db.getParent();
   parent.setChildAt(parent.getIndex(db), (TemplateElement) db.getChildAt(0));
 }
 public void setChildAt(int index, TemplateElement element) {
   if (nestedBlock instanceof MixedContent) {
     nestedBlock.setChildAt(index, element);
   } else if (nestedBlock != null) {
     if (index == 0) {
       nestedBlock = element;
       element.index = 0;
       element.parent = this;
     } else {
       throw new IndexOutOfBoundsException("invalid index");
     }
   } else if (regulatedChildBuffer != null) {
     regulatedChildBuffer[index] = element;
     element.index = index;
     element.parent = this;
   } else {
     throw new IndexOutOfBoundsException("element has no children");
   }
 }
 /**
  * Note: For element with {@code #nestedBlock}, this will hide the {@code #nestedBlock} when
  * that's a {@link MixedContent}.
  */
 public Enumeration children() {
   if (nestedBlock instanceof MixedContent) {
     return nestedBlock.children();
   }
   if (nestedBlock != null) {
     return Collections.enumeration(Collections.singletonList(nestedBlock));
   } else if (regulatedChildBuffer != null) {
     return new _ArrayEnumeration(regulatedChildBuffer, regulatedChildCount);
   }
   return Collections.enumeration(Collections.EMPTY_LIST);
 }
Example #14
0
 /**
  * @return an array of the {@link TemplateElement}s containing the given column and line numbers.
  * @deprecated Should only be used internally, and might will be removed later.
  */
 public TreePath containingElements(int column, int line) {
   final ArrayList elements = new ArrayList();
   TemplateElement element = rootElement;
   mainloop:
   while (element.contains(column, line)) {
     elements.add(element);
     for (Enumeration enumeration = element.children(); enumeration.hasMoreElements(); ) {
       TemplateElement elem = (TemplateElement) enumeration.nextElement();
       if (elem.contains(column, line)) {
         element = elem;
         continue mainloop;
       }
     }
     break;
   }
   if (elements.isEmpty()) {
     return null;
   }
   return new TreePath(elements.toArray());
 }
  final void addRegulatedChild(int index, TemplateElement nestedElement) {
    final int lRegulatedChildCount = regulatedChildCount;

    TemplateElement[] lRegulatedChildBuffer = regulatedChildBuffer;
    if (lRegulatedChildBuffer == null) {
      lRegulatedChildBuffer = new TemplateElement[INITIAL_REGULATED_CHILD_BUFFER_CAPACITY];
      regulatedChildBuffer = lRegulatedChildBuffer;
    } else if (lRegulatedChildCount == lRegulatedChildBuffer.length) {
      setRegulatedChildBufferCapacity(lRegulatedChildCount != 0 ? lRegulatedChildCount * 2 : 1);
      lRegulatedChildBuffer = regulatedChildBuffer;
    }
    // At this point: nestedElements == this.nestedElements, and has sufficient capacity.

    for (int i = lRegulatedChildCount; i > index; i--) {
      TemplateElement movedElement = lRegulatedChildBuffer[i - 1];
      movedElement.index = i;
      lRegulatedChildBuffer[i] = movedElement;
    }
    nestedElement.index = index;
    nestedElement.parent = this;
    lRegulatedChildBuffer[index] = nestedElement;
    regulatedChildCount = lRegulatedChildCount + 1;
  }
 public int getIndex(TemplateElement node) {
   if (nestedBlock instanceof MixedContent) {
     return nestedBlock.getIndex(node);
   }
   if (nestedBlock != null) {
     if (node == nestedBlock) {
       return 0;
     }
   } else {
     for (int i = 0; i < regulatedChildCount; i++) {
       if (regulatedChildBuffer[i].equals(node)) {
         return i;
       }
     }
   }
   return -1;
 }
  private static TemplateElement findTemplateElement(TemplateElement te, int line) {
    if (te.getBeginLine() > line || te.getEndLine() < line) {
      return null;
    }
    // Find the narrowest match
    List childMatches = new ArrayList();
    for (Enumeration children = te.children(); children.hasMoreElements(); ) {
      TemplateElement child = (TemplateElement) children.nextElement();
      TemplateElement childmatch = findTemplateElement(child, line);
      if (childmatch != null) {
        childMatches.add(childmatch);
      }
    }
    // find a match that exactly matches the begin/end line
    TemplateElement bestMatch = null;
    for (int i = 0; i < childMatches.size(); i++) {
      TemplateElement e = (TemplateElement) childMatches.get(i);

      if (bestMatch == null) {
        bestMatch = e;
      }

      if (e.getBeginLine() == line && e.getEndLine() > line) {
        bestMatch = e;
      }

      if (e.getBeginLine() == e.getEndLine() && e.getBeginLine() == line) {
        bestMatch = e;
        break;
      }
    }
    if (bestMatch != null) {
      return bestMatch;
    }
    // If no child provides narrower match, return this
    return te;
  }
 public TemplateElement getChildAt(int index) {
   if (nestedBlock instanceof MixedContent) {
     return nestedBlock.getChildAt(index);
   }
   if (nestedBlock != null) {
     if (index == 0) {
       return nestedBlock;
     }
     throw new ArrayIndexOutOfBoundsException("invalid index");
   } else if (regulatedChildCount != 0) {
     try {
       return regulatedChildBuffer[index];
     } catch (ArrayIndexOutOfBoundsException e) {
       // nestedElements was a List earlier, so we emulate the same kind of exception
       throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + regulatedChildCount);
     }
   }
   throw new ArrayIndexOutOfBoundsException("Template element has no children");
 }
 /** Dump the raw template in canonical form. */
 public void dump(PrintStream ps) {
   ps.print(rootElement.getCanonicalForm());
 }
 /** Dump the raw template in canonical form. */
 public void dump(Writer out) throws IOException {
   out.write(rootElement.getCanonicalForm());
 }
 /**
  * Walk the AST subtree rooted by this element, and do simplifications where possible, also remove
  * superfluous whitespace.
  *
  * @param stripWhitespace whether to remove superfluous whitespace
  * @return The element this element should be replaced with in the parent. If it's the same as
  *     this element, no actual replacement will happen. Note that adjusting the {@link #parent}
  *     and {@link #index} of the result is the duty of the caller, not of this method.
  */
 TemplateElement postParseCleanup(boolean stripWhitespace) throws ParseException {
   int regulatedChildCount = this.regulatedChildCount;
   if (regulatedChildCount != 0) {
     for (int i = 0; i < regulatedChildCount; i++) {
       TemplateElement te = regulatedChildBuffer[i];
       te = te.postParseCleanup(stripWhitespace);
       regulatedChildBuffer[i] = te;
       te.parent = this;
       te.index = i;
     }
     if (stripWhitespace) {
       for (int i = 0; i < regulatedChildCount; i++) {
         TemplateElement te = regulatedChildBuffer[i];
         if (te.isIgnorable()) {
           regulatedChildCount--;
           for (int j = i; j < regulatedChildCount; j++) {
             final TemplateElement te2 = regulatedChildBuffer[j + 1];
             regulatedChildBuffer[j] = te2;
             te2.index = j;
           }
           regulatedChildBuffer[regulatedChildCount] = null;
           this.regulatedChildCount = regulatedChildCount;
           i--;
         }
       }
     }
     if (regulatedChildCount < regulatedChildBuffer.length
         && regulatedChildCount <= regulatedChildBuffer.length * 3 / 4) {
       TemplateElement[] trimmedregulatedChildBuffer = new TemplateElement[regulatedChildCount];
       for (int i = 0; i < regulatedChildCount; i++) {
         trimmedregulatedChildBuffer[i] = regulatedChildBuffer[i];
       }
       regulatedChildBuffer = trimmedregulatedChildBuffer;
     }
   } else if (nestedBlock != null) {
     nestedBlock = nestedBlock.postParseCleanup(stripWhitespace);
     if (nestedBlock.isIgnorable()) {
       nestedBlock = null;
     } else {
       nestedBlock.parent = this;
     }
   }
   return this;
 }