View Javadoc

1   /*
2    * Copyright 2009 - 2010 JEuclid, http://jeuclid.sf.net
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  /* $Id $ */
18  
19  package net.sourceforge.jeuclid.biparser;
20  
21  import org.w3c.dom.Node;
22  
23  /**
24   * this class is used to store typical information about a xml-node.
25   * 
26   * @version $Revision: 0b66106c7ff7 $
27   * 
28   */
29  public abstract class AbstractBiNode implements IBiNode {
30  
31      /** previous node, null if node is root. */
32      private IBiNode previous;
33  
34      /** sibling node, can be null. */
35      private IBiNode sibling;
36  
37      /** reference to node in DOM-tree. */
38      private Node node;
39  
40      /** length of node in characters. */
41      private int length;
42  
43      /**
44       * get previous node, null if node is root.
45       * 
46       * @return previous
47       */
48      public final IBiNode getPrevious() {
49          return this.previous;
50      }
51  
52      /**
53       * set previous for this node.
54       * 
55       * @param prev
56       *            previous node for this node
57       */
58      public final void setPrevious(final IBiNode prev) {
59          this.previous = prev;
60      }
61  
62      /**
63       * get parent node for this node.
64       * 
65       * @return parent
66       */
67      public final BiNode getParent() {
68          // check if previous isn't a "real parent"
69          if (this.previous != null && this.previous.getSibling() == this) {
70              return this.previous.getParent();
71          } else {
72              // previous is "real parent" or null
73              return (BiNode) this.previous;
74          }
75      }
76  
77      /**
78       * get sibling node, can be null.
79       * 
80       * @return sibling
81       */
82      public final IBiNode getSibling() {
83          return this.sibling;
84      }
85  
86      /**
87       * set sibling for this node and set previous of sibling to this.
88       * 
89       * @param sibl
90       *            new sibling for this node
91       */
92      public final void setSibling(final IBiNode sibl) {
93          if (sibl != null) {
94              sibl.setPrevious(this);
95          }
96  
97          this.sibling = sibl;
98      }
99  
100     /**
101      * add sibling to a node, not possible at a textnode. if node already has a
102      * sibling, forward to sibling.
103      * 
104      * @param sibl
105      *            new sibling for this node
106      */
107     public final void addSibling(final IBiNode sibl) {
108         if (this.sibling == null) {
109             // 2nd child
110             this.setSibling(sibl);
111         } else {
112             // forward(3rd - nth child)
113             this.sibling.addSibling(sibl);
114         }
115     }
116 
117     /**
118      * get reference to node in DOM-tree.
119      * 
120      * @return node in DOM-tree
121      */
122     public final Node getNode() {
123         return this.node;
124     }
125 
126     /**
127      * set reference to node in DOM-tree.
128      * 
129      * @param n
130      *            reference in DOM-tree
131      */
132     public final void setNode(final Node n) {
133         this.node = n;
134     }
135 
136     /**
137      * get length of node (number of characters).
138      * 
139      * @return length of node
140      */
141     public final int getLength() {
142         return this.length;
143     }
144 
145     /**
146      * set length of node.
147      * 
148      * @param len
149      *            to set
150      */
151     public final void setLength(final int len) {
152         this.length = len;
153     }
154 
155     /**
156      * change length of node and recursive of all parents.
157      * 
158      * @param change
159      *            changevalue (can be positive or negative)
160      */
161     public final void changeLengthRec(final int change) {
162         if (change == 0) {
163             return;
164         }
165 
166         this.length += change;
167 
168         if (this.getParent() != null) {
169             this.getParent().changeLengthRec(change);
170         }
171     }
172 
173     /**
174      * helper method to insert or remove characters.
175      * 
176      * @param insert
177      *            if true call insert-method else remove-method
178      * @param biTree
179      *            reference to BiTree to which this node contains
180      * @param offset
181      *            position to insert/remove characters
182      * @param len
183      *            number of characters to insert/remove
184      * @param totalOffset
185      *            offset of node to begin of text
186      * @throws ReparseException
187      *             if a reparse at upper level is needed
188      * @throws NonIncrementalElementException
189      *             if the subtree contains an element which cannot be
190      *             incrementally updated.
191      */
192     public void forwardToSibling(final boolean insert, final BiTree biTree,
193             final int offset, final int len, final int totalOffset)
194             throws ReparseException, NonIncrementalElementException {
195 
196         if (this.getSibling() == null) {
197             // reparsing
198             throw new ReparseException();
199         } else {
200             if (insert) {
201                 this.getSibling().insert(biTree, offset, len, totalOffset);
202             } else {
203                 this.getSibling().remove(biTree, offset, len, totalOffset);
204             }
205         }
206     }
207 
208     /**
209      * search a DOM node in this node. if nodes are equal return offset to begin
210      * of inputtext, else null
211      * 
212      * @param n
213      *            DOM node to search for
214      * @param totalOffset
215      *            offset of node to begin of inputtext
216      * @return position of node in inputtext
217      */
218     public TextPosition searchNode(final Node n, final int totalOffset) {
219         if (this.node != null && this.node.equals(n)) {
220             return new TextPosition(totalOffset, this.length);
221         }
222 
223         return null;
224     }
225 
226     /**
227      * helper method for outputting the length of node.
228      * 
229      * @return formatted output of length
230      */
231     public String formatLength() {
232         int i;
233         final int max = 3;
234         final StringBuffer sb = new StringBuffer();
235 
236         for (i = 1; i <= max && 1 > this.getLength() / Math.pow(10, max - i); i++) {
237 
238             if (i == 1 && this.getLength() == 0) {
239                 continue;
240             }
241             sb.append(' ');
242         }
243 
244         sb.append(this.length);
245 
246         return sb.toString();
247     }
248 }