Coverage Report - org.simpleframework.xml.stream.OutputStack
 
Classes in this File Line Coverage Branch Coverage Complexity
OutputStack
86%
20/23
50%
4/8
1.818
OutputStack$Sequence
70%
7/10
75%
3/4
1.818
 
 1  
 /*
 2  
  * OutputStack.java July 2006
 3  
  *
 4  
  * Copyright (C) 2006, Niall Gallagher <niallg@users.sf.net>
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
 15  
  * implied. See the License for the specific language governing 
 16  
  * permissions and limitations under the License.
 17  
  */
 18  
 
 19  
 package org.simpleframework.xml.stream;
 20  
 
 21  
 import java.util.Iterator;
 22  
 import java.util.ArrayList;
 23  
 import java.util.Set;
 24  
 
 25  
 /**
 26  
  * The <code>OutputStack</code> is used to keep track of the nodes 
 27  
  * that have been written to the document. This ensures that when
 28  
  * nodes are written to  the XML document that the writer can tell
 29  
  * whether a child node for a given <code>OutputNode</code> can be
 30  
  * created. Each created node is pushed, and popped when ended.
 31  
  *
 32  
  * @author Niall Gallagher
 33  
  * 
 34  
  * @see org.simpleframework.xml.stream.OutputNode
 35  
  */ 
 36  
 class OutputStack extends ArrayList<OutputNode> {
 37  
 
 38  
    /**
 39  
     * Represents the set of nodes that have not been committed.
 40  
     */         
 41  
    private final Set active;
 42  
   
 43  
    /**
 44  
     * Constructor for the <code>OutputStack</code> object. This is
 45  
     * used to create a stack that can be used to keep track of the
 46  
     * elements that have been written to the XML document.
 47  
     */    
 48  24420
    public OutputStack(Set active) {
 49  24420
       this.active = active;
 50  24420
    }
 51  
 
 52  
    /**
 53  
     * This is used to remove the <code>OutputNode</code> from the
 54  
     * top of the output stack. This is used when an element has been
 55  
     * ended and the output writer wants to block child creation.
 56  
     *
 57  
     * @return this returns the node from the top of the stack
 58  
     */    
 59  
    public OutputNode pop() {
 60  562103
       int size = size();
 61  
       
 62  562103
       if(size <= 0) {
 63  0
          return null;
 64  
       }
 65  562103
       return purge(size - 1);
 66  
    }
 67  
    
 68  
    /**
 69  
     * This is used to acquire the <code>OutputNode</code> from the
 70  
     * top of the output stack. This is used when the writer wants to
 71  
     * determine the current element written to the XML document.
 72  
     *
 73  
     * @return this returns the node from the top of the stack
 74  
     */    
 75  
    public OutputNode top() {
 76  1776667
       int size = size();
 77  
       
 78  1776667
       if(size <= 0) {
 79  0
          return null;              
 80  
       }           
 81  1776667
       return get(size - 1);
 82  
    }
 83  
 
 84  
    /**
 85  
     * This is used to acquire the <code>OutputNode</code> from the
 86  
     * bottom of the output stack. This is used when the writer wants
 87  
     * to determine the root element for the written XML document.
 88  
     *
 89  
     * @return this returns the node from the bottom of the stack
 90  
     */ 
 91  
    public OutputNode bottom() {
 92  26305
       int size = size();
 93  
       
 94  26305
       if(size <= 0) {
 95  0
          return null;              
 96  
       }           
 97  26305
       return get(0);           
 98  
    }
 99  
 
 100  
    /**
 101  
     * This method is used to add an <code>OutputNode</code> to the
 102  
     * top of the stack. This is used when an element is written to
 103  
     * the XML document, and allows the writer to determine if a
 104  
     * child node can be created from a given output node.
 105  
     *
 106  
     * @param value this is the output node to add to the stack
 107  
     */    
 108  
    public OutputNode push(OutputNode value) {
 109  562116
       active.add(value);
 110  562116
       add(value);
 111  562116
       return value;
 112  
    }
 113  
    
 114  
    /**
 115  
     * The <code>purge</code> method is used to purge a match from
 116  
     * the provided position. This also ensures that the active set
 117  
     * has the node removed so that it is no longer relevant.
 118  
     *
 119  
     * @param index the index of the node that is to be removed
 120  
     * 
 121  
     * @return returns the node removed from the specified index
 122  
     */ 
 123  
    public OutputNode purge(int index) {      
 124  562103
       OutputNode node = remove(index);  
 125  
       
 126  562103
       if(node != null){
 127  562103
          active.remove(node);
 128  
       }    
 129  562103
       return node;
 130  
    }
 131  
    
 132  
    /**
 133  
     * This is returns an <code>Iterator</code> that is used to loop
 134  
     * through the ouptut nodes from the top down. This allows the
 135  
     * node writer to determine what <code>Mode</code> should be used
 136  
     * by an output node. This reverses the iteration of the list.
 137  
     * 
 138  
     * @return returns an iterator to iterate from the top down
 139  
     */ 
 140  
    public Iterator<OutputNode> iterator() {
 141  317059
       return new Sequence();              
 142  
    }
 143  
 
 144  
    /**
 145  
     * The is used to order the <code>OutputNode</code> objects from
 146  
     * the top down. This is basically used to reverse the order of
 147  
     * the linked list so that the stack can be iterated within a
 148  
     * for each loop easily. This can also be used to remove a node.
 149  
     *
 150  
     * @author Niall Gallagher
 151  
     */
 152  319066
    private class Sequence implements Iterator<OutputNode> {
 153  
 
 154  
       /**
 155  
        * The cursor used to acquire objects from the stack.
 156  
        */               
 157  
       private int cursor;
 158  
 
 159  
       /**
 160  
        * Constructor for the <code>Sequence</code> object. This is
 161  
        * used to position the cursor at the end of the list so the
 162  
        * last inserted output node is the first returned from this.
 163  
        */ 
 164  317059
       public Sequence() {
 165  317059
          this.cursor = size();                 
 166  317059
       }
 167  
 
 168  
       /**
 169  
        * Returns the <code>OutputNode</code> object at the cursor
 170  
        * position. If the cursor has reached the start of the list 
 171  
        * then this returns null instead of the first output node.
 172  
        * 
 173  
        * @return this returns the node from the cursor position
 174  
        */ 
 175  
       public OutputNode next() {
 176  319066
          if(hasNext()) {
 177  319066
              return get(--cursor);
 178  
          }           
 179  0
          return null;     
 180  
       }    
 181  
 
 182  
       /**
 183  
        * This is used to determine if the cursor has reached the
 184  
        * start of the list. When the cursor reaches the start of
 185  
        * the list then this method returns false.
 186  
        * 
 187  
        * @return this returns true if there are more nodes left
 188  
        */ 
 189  
       public boolean hasNext() {
 190  638246
          return cursor > 0;
 191  
       }
 192  
 
 193  
       /**
 194  
        * Removes the match from the cursor position. This also
 195  
        * ensures that the node is removed from the active set so
 196  
        * that it is not longer considered a relevant output node.
 197  
        */ 
 198  
       public void remove() {                    
 199  0
          purge(cursor);                
 200  0
       }        
 201  
    }
 202  
 }