1 package net.sf.saxon.tinytree; 2 import net.sf.saxon.event.Builder; 3 import net.sf.saxon.event.LocationProvider; 4 import net.sf.saxon.event.ReceiverOptions; 5 import net.sf.saxon.om.FastStringBuffer; 6 import net.sf.saxon.style.StandardNames; 7 import net.sf.saxon.trans.XPathException; 8 import net.sf.saxon.type.Type; 9 10 11 17 18 public class TinyBuilder extends Builder { 19 20 public static final int PARENT_POINTER_INTERVAL = 10; 21 24 private TinyTree tree; 25 26 private int currentDepth = 0; 27 private int nodeNr = 0; private boolean ended = false; 29 private int[] sizeParameters; 31 public void setSizeParameters(int[] params) { 32 sizeParameters = params; 33 } 34 35 public int[] getSizeParameters() { 36 int[] params = {tree.numberOfNodes, tree.numberOfAttributes, tree.numberOfNamespaces, tree.charBufferLength}; 37 return params; 38 } 39 40 private int[] prevAtDepth = new int[100]; 41 45 private int[] siblingsAtDepth = new int[100]; 46 52 private boolean isIDElement = false; 53 54 public TinyTree getTree() { 55 return tree; 56 } 57 58 61 62 public void open() throws XPathException { 63 if (started) { 64 return; 66 } 67 if (tree == null) { 68 if (sizeParameters==null) { 69 tree = new TinyTree(); 70 } else { 71 tree = new TinyTree(sizeParameters[0], 72 sizeParameters[1], sizeParameters[2], sizeParameters[3]); 73 } 74 tree.setConfiguration(config); 75 currentDepth = 0; 76 if (lineNumbering) { 77 tree.setLineNumbering(); 78 } 79 } 80 super.open(); 81 } 82 83 86 87 public void startDocument (int properties) throws XPathException { 88 if ((started && !ended) || currentDepth > 0) { 92 return; 95 } 96 started = true; 97 98 currentRoot = new TinyDocumentImpl(tree); 101 TinyDocumentImpl doc = (TinyDocumentImpl)currentRoot; 102 doc.setSystemId(getSystemId()); 103 doc.setConfiguration(config); 104 117 currentDepth = 0; 118 tree.addDocumentNode((TinyDocumentImpl)currentRoot); 119 prevAtDepth[0] = 0; 120 prevAtDepth[1] = -1; 121 siblingsAtDepth[0] = 0; 122 siblingsAtDepth[1] = 0; 123 tree.next[0] = -1; 124 125 currentDepth++; 126 127 super.startDocument(0); 128 129 } 130 131 134 135 public void endDocument () throws XPathException { 136 138 if (currentDepth > 1) return; 139 141 if (ended) return; ended = true; 143 144 prevAtDepth[currentDepth] = -1; 145 146 147 148 } 150 151 public void close() throws XPathException { 152 tree.addNode(Type.STOPPER, 0, 0, 0, 0); 153 tree.condense(); 154 super.close(); 155 } 156 157 160 161 public void startElement (int nameCode, int typeCode, int locationId, int properties) throws XPathException 162 { 163 167 if (siblingsAtDepth[currentDepth] > PARENT_POINTER_INTERVAL) { 170 nodeNr = tree.addNode(Type.PARENT_POINTER, currentDepth, prevAtDepth[currentDepth-1], 0, 0); 171 int prev = prevAtDepth[currentDepth]; 172 if (prev > 0) { 173 tree.next[prev] = nodeNr; 174 } 175 tree.next[nodeNr] = prevAtDepth[currentDepth-1]; 176 prevAtDepth[currentDepth] = nodeNr; 177 siblingsAtDepth[currentDepth] = 0; 178 } 179 180 nodeNr = tree.addNode(Type.ELEMENT, currentDepth, -1, -1, nameCode); 182 183 isIDElement = false; 184 if (typeCode != StandardNames.XDT_UNTYPED && typeCode != -1) { 185 tree.setElementAnnotation(nodeNr, typeCode); 186 if (tree.isIDCode(typeCode)) { 187 isIDElement = true; 188 } 189 } 190 191 if (currentDepth == 0) { 192 prevAtDepth[0] = nodeNr; 193 prevAtDepth[1] = -1; 194 currentRoot = tree.getNode(nodeNr); 196 } else { 197 int prev = prevAtDepth[currentDepth]; 198 if (prev > 0) { 199 tree.next[prev] = nodeNr; 200 } 201 tree.next[nodeNr] = prevAtDepth[currentDepth - 1]; prevAtDepth[currentDepth] = nodeNr; 203 siblingsAtDepth[currentDepth]++; 204 } 205 currentDepth++; 206 207 if (currentDepth == prevAtDepth.length) { 208 int[] p2 = new int[currentDepth*2]; 209 System.arraycopy(prevAtDepth, 0, p2, 0, currentDepth); 210 prevAtDepth = p2; 211 p2 = new int[currentDepth*2]; 212 System.arraycopy(siblingsAtDepth, 0, p2, 0, currentDepth); 213 siblingsAtDepth = p2; 214 } 215 prevAtDepth[currentDepth] = -1; 216 siblingsAtDepth[currentDepth] = 0; 217 218 LocationProvider locator = pipe.getLocationProvider(); 219 if (locator != null) { 220 tree.setSystemId(nodeNr, locator.getSystemId(locationId)); 221 if (lineNumbering) { 222 tree.setLineNumber(nodeNr, locator.getLineNumber(locationId)); 223 } 224 } 225 } 226 227 public void namespace(int namespaceCode, int properties) throws XPathException { 228 tree.addNamespace( nodeNr, namespaceCode ); 229 } 230 231 public void attribute(int nameCode, int typeCode, CharSequence value, int locationId, int properties) 232 throws XPathException { 233 235 properties &= ~ReceiverOptions.DISABLE_ESCAPING; 236 tree.addAttribute(currentRoot, nodeNr, nameCode, typeCode, value, properties); 237 } 238 239 public void startContent() { 240 nodeNr++; 241 } 242 243 246 247 public void endElement () throws XPathException { 248 prevAtDepth[currentDepth] = -1; 249 siblingsAtDepth[currentDepth] = 0; 250 currentDepth--; 251 if (isIDElement) { 252 tree.indexIDElement(currentRoot, prevAtDepth[currentDepth]); 253 isIDElement = false; 254 } 255 } 256 257 260 261 public void characters (CharSequence chars, int locationId, int properties) throws XPathException 262 { 263 if (chars.length()>0) { 264 int bufferStart = tree.charBufferLength; 266 tree.appendChars(chars); 267 int n=tree.numberOfNodes-1; 268 if (tree.nodeKind[n] == Type.TEXT && tree.depth[n] == currentDepth) { 269 tree.beta[n] += chars.length(); 271 } else { 272 nodeNr = tree.addNode(Type.TEXT, currentDepth, bufferStart, chars.length(), -1); 273 274 int prev = prevAtDepth[currentDepth]; 275 if (prev > 0) { 276 tree.next[prev] = nodeNr; 277 } 278 tree.next[nodeNr] = prevAtDepth[currentDepth - 1]; prevAtDepth[currentDepth] = nodeNr; 280 siblingsAtDepth[currentDepth]++; 281 } 282 } 283 } 284 285 288 289 public void processingInstruction (String piname, CharSequence remainder, int locationId, int properties) throws XPathException 290 { 291 if (tree.commentBuffer==null) { 292 tree.commentBuffer = new FastStringBuffer(200); 293 } 294 int s = tree.commentBuffer.length(); 295 tree.commentBuffer.append(remainder.toString()); 296 int nameCode = namePool.allocate("", "", piname); 297 298 nodeNr = tree.addNode(Type.PROCESSING_INSTRUCTION, currentDepth, s, remainder.length(), 299 nameCode); 300 301 int prev = prevAtDepth[currentDepth]; 302 if (prev > 0) { 303 tree.next[prev] = nodeNr; 304 } 305 tree.next[nodeNr] = prevAtDepth[currentDepth - 1]; prevAtDepth[currentDepth] = nodeNr; 307 siblingsAtDepth[currentDepth]++; 308 309 LocationProvider locator = pipe.getLocationProvider(); 310 if (locator != null) { 311 tree.setSystemId(nodeNr, locator.getSystemId(locationId)); 312 if (lineNumbering) { 313 tree.setLineNumber(nodeNr, locator.getLineNumber(locationId)); 314 } 315 } 316 } 317 318 321 322 public void comment (CharSequence chars, int locationId, int properties) throws XPathException { 323 if (tree.commentBuffer==null) { 324 tree.commentBuffer = new FastStringBuffer(200); 325 } 326 int s = tree.commentBuffer.length(); 327 tree.commentBuffer.append(chars.toString()); 328 nodeNr = tree.addNode(Type.COMMENT, currentDepth, s, chars.length(), -1); 329 330 int prev = prevAtDepth[currentDepth]; 331 if (prev > 0) { 332 tree.next[prev] = nodeNr; 333 } 334 tree.next[nodeNr] = prevAtDepth[currentDepth - 1]; prevAtDepth[currentDepth] = nodeNr; 336 siblingsAtDepth[currentDepth]++; 337 338 } 339 340 343 344 public void setUnparsedEntity(String name, String uri, String publicId) { 345 ((TinyDocumentImpl)currentRoot).setUnparsedEntity(name, uri, publicId); 346 } 347 348 } 349 350 | Popular Tags |