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 java.util.ArrayList;
22 import java.util.List;
23
24 import net.sourceforge.jeuclid.elements.JEuclidElementFactory;
25
26 import org.xml.sax.Attributes;
27 import org.xml.sax.SAXParseException;
28
29 /**
30 * this class if for creating a BiTree with ABiNodes while parsing a text.
31 *
32 * @version $Revision: 0b66106c7ff7 $
33 */
34 public class BiTreeCreationHelper {
35
36 /** current position in tree. */
37 private IBiNode currentBiNode;
38 /** root of tree. */
39 private IBiNode root;
40 /** save positions of open tags. */
41 private final List<Integer> startPositions;
42
43 /**
44 * create a new BiTreeHelper. get result (tree of ABiNodes) with getRoot()
45 */
46 public BiTreeCreationHelper() {
47 this.startPositions = new ArrayList<Integer>();
48 }
49
50 /**
51 * get root of BiTree.
52 *
53 * @return root of BiTree
54 */
55 public final IBiNode getRoot() {
56 return this.root;
57 }
58
59 /**
60 * create and append a new BiNode at current position in BiTree.
61 *
62 * @param totalOffset
63 * of node in text
64 * @param childOffset
65 * position of first child (length of open tag)
66 * @param namespaceURI
67 * namespace
68 * @param eName
69 * name of node
70 * @param attrs
71 * attributes of node
72 * @throws SAXParseException
73 * if the element cannot be recognized by JEuclid.
74 */
75 public final void createBiNode(final int totalOffset,
76 final int childOffset, final String namespaceURI,
77 final String eName, final Attributes attrs) throws SAXParseException {
78
79 if (JEuclidElementFactory.getJEuclidElementConstructor(namespaceURI,
80 eName) == null) {
81 throw new NonIncrementalElementException(eName);
82 }
83 BiNode biNode;
84
85 this.startPositions.add(totalOffset);
86
87 // new root node
88 if (this.root == null) {
89 this.root = new BiNode(childOffset, namespaceURI, eName, attrs);
90 this.currentBiNode = this.root;
91 } else {
92 biNode = new BiNode(childOffset, namespaceURI, eName, attrs);
93
94 // append child (only possible at start
95 if (this.currentBiNode.getType() == BiType.EMPTY) {
96 this.currentBiNode.addSibling(biNode);
97 } else {
98 // add child (default case)
99 ((BiNode) this.currentBiNode).addChild(biNode);
100 }
101
102 this.currentBiNode = biNode;
103 }
104 }
105
106 /**
107 * close BiNode (set length of node).
108 *
109 * @param length
110 * length of node
111 */
112 public final void closeBiNode(final int length) {
113 BiNode parent;
114 final int last = this.startPositions.size() - 1;
115
116 this.currentBiNode.setLength(length - this.startPositions.get(last));
117
118 // move current position to parent
119 parent = this.currentBiNode.getParent();
120 if (parent != null) {
121 this.currentBiNode = parent;
122 }
123
124 this.startPositions.remove(last);
125 }
126
127 /**
128 * check if current position in BiTree allows a TextNode as child.
129 *
130 * @return true if a TextNode is allowed
131 */
132 public final boolean allowNewTextNode() {
133 return ((BiNode) this.currentBiNode).getChild() == null;
134 }
135
136 /**
137 * create a new TextNode at current position.
138 *
139 * @param length
140 * length of TextNode
141 * @param t
142 * text of TextNode
143 */
144 public final void createTextNode(final int length, final String t) {
145 ((BiNode) this.currentBiNode).addChild(new TextNode(length, t));
146 }
147
148 /**
149 * create a new EmptyNode at current position in BiTree.
150 *
151 * @param length
152 * length of EmtpyNode
153 */
154 public final void createEmtpyNode(final int length) {
155 // EmptyNode is new root
156 if (this.root == null) {
157 this.root = new EmptyNode(length);
158 this.currentBiNode = this.root;
159 } else {
160 ((BiNode) this.currentBiNode).addChild(new EmptyNode(length));
161 }
162 }
163 }