001    /*
002     * Copyright 2009 - 2010 JEuclid, http://jeuclid.sf.net
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    /* $Id $ */
018    
019    package net.sourceforge.jeuclid.biparser;
020    
021    import net.sourceforge.jeuclid.elements.generic.DocumentElement;
022    
023    import org.w3c.dom.Document;
024    import org.w3c.dom.Node;
025    import org.w3c.dom.NodeList;
026    
027    /**
028     * this class if for creating a BiTree with ABiNodes while parsing a text.
029     * 
030     * @version $Revision: 0b66106c7ff7 $
031     */
032    public class BiTree {
033    
034        /** document (DOM-tree). */
035        private Document doc;
036    
037        /** root of tree. */
038        private IBiNode root;
039    
040        /** text of tree. */
041        private String text;
042    
043        /**
044         * create a new instance of BiTree.
045         */
046        public BiTree() {
047    
048        }
049    
050        /**
051         * create a new DOM tree from bitree and save it.
052         */
053        public final void createDOMTree() {
054            Node subtree;
055    
056            this.doc = new DocumentElement();
057    
058            subtree = this.getDOMTree(this.doc);
059    
060            if (subtree != null) {
061                this.doc.appendChild(subtree);
062            }
063        }
064    
065        /**
066         * create a dom tree from bitree and return root.
067         * 
068         * @param d
069         *            document to create DOM tree
070         * @return root of DOM tree
071         */
072        public final Node getDOMTree(final Document d) {
073            Node treeRoot;
074    
075            if (this.root.getType() == BiType.EMPTY) {
076                treeRoot = this.root.getSibling().createDOMSubtree(d);
077            } else {
078                treeRoot = this.root.createDOMSubtree(d);
079            }
080    
081            return treeRoot;
082        }
083    
084        /**
085         * get root of BiTree.
086         * 
087         * @return root of BiTree
088         */
089        public final IBiNode getRoot() {
090            return this.root;
091        }
092    
093        /**
094         * insert characters into BiTree.
095         * 
096         * @param offset
097         *            insert position in text
098         * @param length
099         *            number of characters to insert
100         * @param t
101         *            text where characters were inserted
102         * @throws ReparseException
103         *             if a sax parse exception occurs
104         * @throws NonIncrementalElementException
105         *             if the subtree contains an element which cannot be
106         *             incrementally updated.
107         */
108        public final void insert(final int offset, final int length, final String t)
109                throws ReparseException, NonIncrementalElementException {
110            this.text = t;
111            this.root.insert(this, offset, length, 0);
112        }
113    
114        /**
115         * remove characters from BiTree.
116         * 
117         * @param offset
118         *            remove position in text
119         * @param length
120         *            number of characters to remove
121         * @param t
122         *            text where characters were removed
123         * @throws ReparseException
124         *             if a sax parse exception occurs
125         * @throws NonIncrementalElementException
126         *             if the subtree contains an element which cannot be
127         *             incrementally updated.
128         */
129        public final void remove(final int offset, final int length, final String t)
130                throws ReparseException, NonIncrementalElementException {
131            this.text = t;
132            this.root.remove(this, offset, length, 0);
133        }
134    
135        /**
136         * set a new root in BiTree.
137         * 
138         * @param r
139         *            new root of BiTree
140         */
141        public final void setRoot(final IBiNode r) {
142    
143            if (r == null) {
144                this.doc = null;
145            } else {
146                r.setPrevious(null);
147            }
148    
149            this.root = r;
150        }
151    
152        /**
153         * get text of BiTree.
154         * 
155         * @return text of BiTree
156         */
157        public String getText() {
158            return this.text;
159        }
160    
161        /**
162         * get document of DOM Tree.
163         * 
164         * @return document of DOM Tree
165         */
166        public Node getDocument() {
167            return this.doc;
168        }
169    
170        /**
171         * search a DOM node in BiTree and return position of node. if node is not
172         * found return null
173         * 
174         * @param node
175         *            DOM node to search for
176         * @return search result of node in inputtext
177         */
178        public TextPosition searchNode(final Node node) {
179            if (this.root == null) {
180                return null;
181            } else {
182                return this.root.searchNode(node, 0);
183            }
184        }
185    
186        /**
187         * get a formatted output of BiTree.
188         * 
189         * @return formatted output of BiTree
190         */
191        @Override
192        public String toString() {
193            if (this.root == null) {
194                return "root is null";
195            } else {
196                return this.root.toString(0);
197            }
198        }
199    
200        /**
201         * get formatted output of DOM Tree (for debugging).
202         * 
203         * @return formatted ouput of DOM Tree
204         */
205        public String toStringDOM() {
206            return this.toStringDOM(0, this.doc.getDocumentElement());
207        }
208    
209        private String toStringDOM(final int level, final Node n) {
210            int i;
211            NodeList nl;
212            final StringBuilder sb = new StringBuilder(128);
213    
214            if (n == null) {
215                return "node is null";
216            }
217    
218            for (i = 0; i < level; i++) {
219                sb.append(" ");
220            }
221    
222            sb.append(" ");
223            if (n.getNodeType() == Node.TEXT_NODE) {
224                sb.append(n.getTextContent());
225            } else {
226                sb.append(n.getNodeName());
227            }
228            sb.append("\n");
229    
230            nl = n.getChildNodes();
231            for (i = 0; i < nl.getLength(); i++) {
232                sb.append(this.toStringDOM(level + 1, nl.item(i)));
233            }
234    
235            return sb.toString();
236        }
237    }