Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2014 Attila Szegedi, Daniel Dekany, Jonathan Revusky
   * 
   * 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 freemarker.core;
 
 
Internal API - subject to change: Represent directive call, interpolation, text block, or other such non-expression node in the parsed template. Some information that can be found here can be accessed through the Environment.getCurrentDirectiveCallPlace(), which a published API, and thus promises backward compatibility.

Deprecated:
This is an internal FreeMarker API with no backward compatibility guarantees, so you shouldn't depend on it.
 
 abstract public class TemplateElement extends TemplateObject {
 
     private static final int INITIAL_REGULATED_CHILD_BUFFER_CAPACITY = 6;
 
     private TemplateElement parent;

    
Used by elements that has no fixed schema for its child elements. For example, a #case can enclose any kind of elements. Only one of nestedBlock and regulatedChildBuffer can be non-null. This element is typically a MixedContent, at least before postParseCleanup(boolean) (which optimizes out MixedContent with child count less than 2).
 
     private TemplateElement nestedBlock;
    
    
Used by elements that has a fixed schema for its child elements. For example, #switch can only have #case and #default child elements. Only one of nestedBlock and regulatedChildBuffer can be non-null.
 
     private int regulatedChildCount;

    
The index of the element in the parent's regulatedChildBuffer array, or 0 if this is the nestedBlock of the parent.

Since:
2.3.23
 
     private int index;

    
Processes the contents of this TemplateElement and outputs the resulting text

Parameters:
env The runtime environment
 
     abstract void accept(Environment envthrows TemplateExceptionIOException;

    
One-line description of the element, that contain all the information that is used in getCanonicalForm(), except the nested content (elements) of the element. The expressions inside the element (the parameters) has to be shown. Meant to be used for stack traces, also for tree views that don't go down to the expression-level. There are no backward-compatibility guarantees regarding the format used ATM, but it must be regular enough to be machine-parseable, and it must contain all information necessary for restoring an AST equivalent to the original. This final implementation calls dump(false).

 
     public final String getDescription() {
         return dump(false);
     }
    
    
This final implementation calls dump(false).
 
     public final String getCanonicalForm() {
         return dump(true);
     }
    
    
Tells if the element should show up in error stack traces. If you think you need to set this to false for an element, always consider if you should use Environment.visitByHiddingParent(freemarker.core.TemplateElement) instead. Note that this will be ignored for the top (current) element of a stack trace, as that's always shown.
    boolean isShownInStackTrace() {
        return true;
    }
    
    
Tells if this element possibly executes its nestedBlock for many times. This flag is useful when a template AST is modified for running time limiting (see ThreadInterruptionSupportTemplatePostProcessor). Elements that use regulatedChildBuffer should not need this, as the insertion of the timeout checks is impossible there, given their rigid nested element schema.
    abstract boolean isNestedBlockRepeater();

    
Brings the implementation of getCanonicalForm() and getDescription() to a single place. Don't call those methods in method on this, because that will result in infinite recursion!

Parameters:
canonical if true, it calculates the return value of getCanonicalForm(), otherwise of getDescription().
    abstract protected String dump(boolean canonical);
    
// Methods to implement TemplateNodeModel 
    public TemplateNodeModel getParentNode() {
//        return parent;
         return null;
    }
    
    public String getNodeNamespace() {
        return null;
    }
    
    public String getNodeType() {
        return "element";
    }
    
        if ( != null) {
            final SimpleSequence seq = new SimpleSequence();
            for (int i = 0; i < i++) {
                seq.add([i]);
            }
            return seq;
        }
        SimpleSequence result = new SimpleSequence(1);
        if ( != null) {
            result.add();
        } 
        return result;
    }
    
    public String getNodeName() {
        String classname = this.getClass().getName();
        int shortNameOffset = classname.lastIndexOf('.')+1;
        return classname.substring(shortNameOffset);
    }
    
    // Methods so that we can implement the Swing TreeNode API.    
    public boolean isLeaf() {
        return  == null &&  == 0;
    }

    

Deprecated:
Meaningless; simply returns if the node currently has any child nodes.
    public boolean getAllowsChildren() {
        return !isLeaf();
    }
    public int getIndex(TemplateElement node) {
        if ( instanceof MixedContent) {
            return .getIndex(node);
        }
        if ( != null) {
            if (node == ) {
                return 0;
            }
        } else {
            for (int i = 0; i < i++) {
                if ([i].equals(node)) { 
                    return i;
                }
            }
        }
        return -1;
    }
    public int getChildCount() {
        if ( instanceof MixedContent) {
            return .getChildCount();
        }
        if ( != null) {
            return 1;
        }
        return ;
    }

    
Note: For element with #nestedBlock, this will hide the #nestedBlock when that's a MixedContent.
    public Enumeration children() {
        if ( instanceof MixedContent) {
            return .children();
        }
        if ( != null) {
            return Collections.enumeration(Collections.singletonList());
        }
        else if ( != null) {
            return new _ArrayEnumeration();
        }
        return Collections.enumeration(.);
    }
    public TemplateElement getChildAt(int index) {
        if ( instanceof MixedContent) {
            return .getChildAt(index);
        }
        if ( != null) {
            if (index == 0) {
                return ;
            }
            throw new ArrayIndexOutOfBoundsException("invalid index");
        }
        else if ( != 0) {
            try {
                return [index];
            } catch (ArrayIndexOutOfBoundsException e) {
                // nestedElements was a List earlier, so we emulate the same kind of exception
                throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + );
            }
        }
        throw new ArrayIndexOutOfBoundsException("Template element has no children");
    }
    public void setChildAt(int indexTemplateElement element) {
        if( instanceof MixedContent) {
            .setChildAt(indexelement);
        }
        else if( != null) {
            if(index == 0) {
                 = element;
                element.index = 0;
                element.parent = this;
            }
            else {
                throw new IndexOutOfBoundsException("invalid index");
            }
        }
        else if( != null) {
            [index] = element;
            element.index = index;
            element.parent = this;
        }
        else {
            throw new IndexOutOfBoundsException("element has no children");
        }
    }
    
    
The element whose child this element is, or null if this is the root node.

Deprecated:
Don't use in internal code either; use getParentElement() there.
    public TemplateElement getParent() {
        return ;
    }
    
    final void setRegulatedChildBufferCapacity(int capacity) {
        int ln = ;
        TemplateElement[] newRegulatedChildBuffer = new TemplateElement[capacity];
        for (int i = 0; i < lni++) {
            newRegulatedChildBuffer[i] = [i];
        }
         = newRegulatedChildBuffer;
    }
    
    final void addRegulatedChild(TemplateElement nestedElement) {
        addRegulatedChild(nestedElement);
    }
    final void addRegulatedChild(int indexTemplateElement nestedElement) {
        final int lRegulatedChildCount = ;
        
        TemplateElement[] lRegulatedChildBuffer = ;
        if (lRegulatedChildBuffer == null) {
            lRegulatedChildBuffer = new TemplateElement[];
             = lRegulatedChildBuffer;
        } else if (lRegulatedChildCount == lRegulatedChildBuffer.length) {
            setRegulatedChildBufferCapacity(lRegulatedChildCount != 0 ? lRegulatedChildCount * 2 : 1);
            lRegulatedChildBuffer = 
        }
        // At this point: nestedElements == this.nestedElements, and has sufficient capacity.
        for (int i = lRegulatedChildCounti > indexi--) {
            TemplateElement movedElement = lRegulatedChildBuffer[i - 1];
            movedElement.index = i;
            lRegulatedChildBuffer[i] = movedElement;
        }
        nestedElement.index = index;
        nestedElement.parent = this;
        lRegulatedChildBuffer[index] = nestedElement;
         = lRegulatedChildCount + 1;
    }
    
    final int getRegulatedChildCount() {
       return 
    }
    
    final TemplateElement getRegulatedChild(int index) {
        return [index];
    }
    
    final int getIndex() {
        return ;
    }
    
    
The element whose child this element is, or null if this is the root node.
        return ;
    }
    
    final TemplateElement getNestedBlock() {
        return ;
    }
    final void setNestedBlock(TemplateElement nestedBlock) {
        if (nestedBlock != null) {
            nestedBlock.parent = this;
            nestedBlock.index = 0;
        }
        this. = nestedBlock;
    }
    
    
This is a special case, because a root element is not contained in another element, so we couldn't set the private fields.
    final void setFieldsForRootElement() {
         = 0;
         = null;
    }

    
Walk the AST subtree rooted by this element, and do simplifications where possible, also remove superfluous whitespace.

Parameters:
stripWhitespace whether to remove superfluous whitespace
Returns:
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 parent and index of the result is the duty of the caller, not of this method.
    TemplateElement postParseCleanup(boolean stripWhitespacethrows ParseException {
        int regulatedChildCount = this.;
        if (regulatedChildCount != 0) {
            for (int i = 0; i < regulatedChildCounti++) {
                TemplateElement te = [i];
                te = te.postParseCleanup(stripWhitespace);
                [i] = te;
                te.parent = this;
                te.index = i;
            }
            if (stripWhitespace) {
                for (int i = 0; i < regulatedChildCounti++) {
                    TemplateElement te = [i];
                    if (te.isIgnorable()) {
                        regulatedChildCount--;
                        for (int j = ij < regulatedChildCountj++) {
                            final TemplateElement te2 = [j  + 1];
                            [j] = te2;
                            te2.index = j;
                        }
                        [regulatedChildCount] = null;
                        this. = regulatedChildCount;
                        i--;
                    }
                }
            }
            if (regulatedChildCount < .
                    && regulatedChildCount <= . * 3 / 4) {
                TemplateElement[] trimmedregulatedChildBuffer = new TemplateElement[regulatedChildCount];
                for (int i = 0; i < regulatedChildCounti++) {
                    trimmedregulatedChildBuffer[i] = [i];
                }
                 = trimmedregulatedChildBuffer;
            }
        } else if ( != null) {
             = .postParseCleanup(stripWhitespace);
            if (.isIgnorable()) {
                 = null;
            } else {
                . = this;
            }
        }
        return this;
    }
    boolean isIgnorable() {
        return false;
    }
// The following methods exist to support some fancier tree-walking 
// and were introduced to support the whitespace cleanup feature in 2.2
        TemplateElement prev = previousSibling();
        if (prev != null) {
            return prev.getLastLeaf();
        }
        else if ( != null) {
            return .prevTerminalNode();
        }
        return null;
    }
        TemplateElement next = nextSibling();
        if (next != null) {
            return next.getFirstLeaf();
        }
        else if ( != null) {
            return .nextTerminalNode();
        }
        return null;
    }
        if ( == null) {
            return null;
        }
        return  > 0 ? .[ - 1] : null;
    }
        if ( == null) {
            return null;
        }
        return  + 1 < . ? .[ + 1] : null;
    }
    private TemplateElement getFirstChild() {
        if ( != null) {
            return ;
        }
        if ( == 0) {
            return null;
        }
        return [0];
    }
    private TemplateElement getLastChild() {
        if ( != null) {
            return ;
        }
        final int regulatedChildCount = this.;
        if (regulatedChildCount == 0) {
            return null;
        }
        return [regulatedChildCount - 1];
    }
    private TemplateElement getFirstLeaf() {
        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.getFirstChild();
        }
        return te;
    }
    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;
    }

    
Tells if executing this element has output that only depends on the template content and that has no side effects.
    boolean isOutputCacheable() {
        return false;
    }
    
    
determines whether this element's presence on a line indicates that we should not strip opening whitespace in the post-parse whitespace gobbling step.
    boolean heedsOpeningWhitespace() {
        return false;
    }

    
determines whether this element's presence on a line indicates that we should not strip trailing whitespace in the post-parse whitespace gobbling step.
    boolean heedsTrailingWhitespace() {
        return false;
    }
New to GrepCode? Check out our FAQ X