1 package net.sf.saxon.tree; 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.AttributeCollectionImpl; 6 import net.sf.saxon.om.DocumentInfo; 7 import net.sf.saxon.om.NodeInfo; 8 import net.sf.saxon.trans.DynamicError; 9 import net.sf.saxon.trans.XPathException; 10 11 import java.util.ArrayList ; 12 13 14 19 20 public class TreeBuilder extends Builder 21 22 { 23 private static AttributeCollectionImpl emptyAttributeCollection = 24 new AttributeCollectionImpl(null); 25 26 private ParentNodeImpl currentNode; 27 28 private NodeFactory nodeFactory; 29 private int[] size = new int[100]; private int depth = 0; 31 private ArrayList arrays = new ArrayList (20); private int pendingElement; 33 private int pendingLocationId; 34 private AttributeCollectionImpl attributes; 35 private int[] namespaces; 36 private int namespacesUsed; 37 38 private int nextNodeNumber = 1; 39 private static final int[] EMPTY_ARRAY_OF_INT = new int[0]; 40 41 44 45 public TreeBuilder() { 46 nodeFactory = new DefaultNodeFactory(); 47 } 49 50 53 54 public void setNodeFactory(NodeFactory factory) { 55 nodeFactory = factory; 56 } 57 58 62 65 66 public void open () throws XPathException 67 { 68 started = true; 71 72 DocumentImpl doc; 73 if (currentRoot==null) { 74 doc = new DocumentImpl(); 76 currentRoot = doc; 77 } else { 78 if (!(currentRoot instanceof DocumentImpl)) { 80 throw new DynamicError("Document node supplied is of wrong kind (" + 81 currentRoot.getClass().getName() + ')'); 82 } 83 doc = (DocumentImpl)currentRoot; 84 if (doc.getFirstChild()!=null) { 85 throw new DynamicError("Supplied document is not empty"); 86 } 87 88 } 89 90 doc.setSystemId(getSystemId()); 91 doc.setConfiguration(config); 92 currentNode = doc; 93 depth = 0; 94 size[depth] = 0; 95 doc.sequence = 0; 96 if (lineNumbering) { 99 doc.setLineNumbering(); 100 } 101 102 super.open(); 103 } 104 105 108 109 public void close () throws XPathException 110 { 111 if (currentNode==null) return; currentNode.compact(size[depth]); 114 currentNode = null; 115 116 arrays = null; 119 120 super.close(); 121 nodeFactory = null; 122 123 } 124 125 128 129 public void startElement (int nameCode, int typeCode, int locationId, int properties) throws XPathException { 130 132 pendingElement = nameCode; 133 pendingLocationId = locationId; 134 namespaces = null; 135 namespacesUsed = 0; 136 attributes = null; 137 } 138 139 public void namespace (int namespaceCode, int properties) { 140 if (namespaces==null) { 141 namespaces = new int[5]; 142 } 143 if (namespacesUsed == namespaces.length) { 144 int[] ns2 = new int[namespaces.length * 2]; 145 System.arraycopy(namespaces, 0, ns2, 0, namespacesUsed); 146 namespaces = ns2; 147 } 148 namespaces[namespacesUsed++] = namespaceCode; 149 } 150 151 public void attribute(int nameCode, int typeCode, CharSequence value, int locationId, int properties) 152 throws XPathException { 153 154 properties &= ~ReceiverOptions.DISABLE_ESCAPING; 158 159 if (attributes==null) { 160 attributes = new AttributeCollectionImpl(namePool); 161 } 162 attributes.addAttribute(nameCode, typeCode, value.toString(), locationId, properties); 167 } 168 169 public void startContent() throws XPathException { 170 if (attributes == null) { 172 attributes = emptyAttributeCollection; 173 } else { 174 attributes.compact(); 175 } 176 177 if (namespaces == null) { 178 namespaces = EMPTY_ARRAY_OF_INT; 179 } 180 181 ElementImpl elem = nodeFactory.makeElementNode( currentNode, 182 pendingElement, 183 attributes, 184 namespaces, 185 namespacesUsed, 186 pipe.getLocationProvider(), 187 pendingLocationId, 188 nextNodeNumber++); 189 190 namespaces = null; 191 namespacesUsed = 0; 192 attributes = null; 193 194 198 while (depth >= arrays.size()) { 199 arrays.add(new NodeImpl[20]); 200 } 201 elem.useChildrenArray((NodeImpl[])arrays.get(depth)); 202 203 currentNode.addChild(elem, size[depth]++); 204 if (depth >= size.length - 1) { 205 int[] newsize = new int[size.length * 2]; 206 System.arraycopy(size, 0, newsize, 0, size.length); 207 size = newsize; 208 } 209 size[++depth] = 0; 210 namespacesUsed = 0; 211 212 if (currentNode instanceof DocumentInfo) { 213 ((DocumentImpl)currentNode).setDocumentElement(elem); 214 } 215 216 currentNode = elem; 217 } 218 219 222 223 public void endElement () throws XPathException 224 { 225 currentNode.compact(size[depth]); 227 depth--; 228 currentNode = (ParentNodeImpl)currentNode.getParent(); 229 } 230 231 234 235 public void characters (CharSequence chars, int locationId, int properties) throws XPathException 236 { 237 if (chars.length()>0) { 239 240 244 TextImpl n = new TextImpl(currentNode, chars.toString()); 247 currentNode.addChild(n, size[depth]++); 248 } 249 } 250 251 254 255 public void processingInstruction (String name, CharSequence remainder, int locationId, int properties) 256 { 257 int nameCode = namePool.allocate("", "", name); 258 ProcInstImpl pi = new ProcInstImpl(nameCode, remainder.toString()); 259 currentNode.addChild(pi, size[depth]++); 260 LocationProvider locator = pipe.getLocationProvider(); 261 if (locator!=null) { 262 pi.setLocation(locator.getSystemId(locationId), 263 locator.getLineNumber(locationId)); 264 } 265 } 266 267 270 271 public void comment (CharSequence chars, int locationId, int properties) throws XPathException { 272 CommentImpl comment = new CommentImpl(chars.toString()); 273 currentNode.addChild(comment, size[depth]++); 274 } 275 276 277 283 284 public void graftElement(ElementImpl element) throws XPathException { 285 currentNode.addChild(element, size[depth]++); 286 } 287 288 291 292 public void setUnparsedEntity(String name, String uri, String publicId) { 293 ((DocumentImpl)currentRoot).setUnparsedEntity(name, uri, publicId); 294 } 295 296 297 302 private static class DefaultNodeFactory implements NodeFactory { 303 304 public ElementImpl makeElementNode( 305 NodeInfo parent, 306 int nameCode, 307 AttributeCollectionImpl attlist, 308 int[] namespaces, 309 int namespacesUsed, 310 LocationProvider locator, 311 int locationId, 312 int sequenceNumber) 313 314 { 315 ElementImpl e; 316 if (attlist.getLength()==0 && namespacesUsed==0) { 317 e = new ElementImpl(); 319 } else { 320 e = new ElementWithAttributes(); 321 if (namespacesUsed > 0) { 322 ((ElementWithAttributes)e).setNamespaceDeclarations(namespaces, namespacesUsed); 323 } 324 } 325 String baseURI = null; 326 int lineNumber = -1; 327 328 if (locator!=null) { 329 baseURI = locator.getSystemId(locationId); 330 lineNumber = locator.getLineNumber(locationId); 331 } 332 333 e.initialise(nameCode, attlist, parent, baseURI, lineNumber, sequenceNumber); 334 return e; 335 } 336 } 337 338 } 339 340 | Popular Tags |