1 /*
2 * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package com.sun.tools.internal.xjc.reader.internalizer;
27
28 import com.sun.xml.internal.bind.unmarshaller.DOMScanner;
29
30 import org.w3c.dom.Document;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.Node;
33 import org.xml.sax.Attributes;
34 import org.xml.sax.ContentHandler;
35 import org.xml.sax.Locator;
36 import org.xml.sax.SAXException;
37 import org.xml.sax.helpers.XMLFilterImpl;
38
39
40
41 /**
42 * Produces a complete series of SAX events from any DOM node
43 * in the DOMForest.
44 *
45 * <p>
46 * This class hides a logic of re-associating {@link Locator}
47 * to the generated SAX event stream.
48 *
49 * @author
50 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
51 */
52 public class DOMForestScanner {
53
54 private final DOMForest forest;
55
56 /**
57 * Scans DOM nodes of the given forest.
58 *
59 * DOM node parameters to the scan method must be a part of
60 * this forest.
61 */
62 public DOMForestScanner( DOMForest _forest ) {
63 this.forest = _forest;
64 }
65
66 /**
67 * Generates the whole set of SAX events by treating
68 * element e as if it's a root element.
69 */
70 public void scan( Element e, ContentHandler contentHandler ) throws SAXException {
71 DOMScanner scanner = new DOMScanner();
72
73 // insert the location resolver into the pipe line
74 LocationResolver resolver = new LocationResolver(scanner);
75 resolver.setContentHandler(contentHandler);
76
77 // parse this DOM.
78 scanner.setContentHandler(resolver);
79 scanner.scan(e);
80 }
81
82 /**
83 * Generates the whole set of SAX events from the given Document
84 * in the DOMForest.
85 */
86 public void scan( Document d, ContentHandler contentHandler ) throws SAXException {
87 scan( d.getDocumentElement(), contentHandler );
88 }
89
90 /**
91 * Intercepts the invocation of the setDocumentLocator method
92 * and passes itself as the locator.
93 *
94 * If the client calls one of the methods on the Locator interface,
95 * use the LocatorTable to resolve the source location.
96 */
97 private class LocationResolver extends XMLFilterImpl implements Locator {
98 LocationResolver( DOMScanner _parent ) {
99 this.parent = _parent;
100 }
101
102 private final DOMScanner parent;
103
104 /**
105 * Flag that tells us whether we are processing a start element event
106 * or an end element event.
107 *
108 * DOMScanner's getCurrentLocation method doesn't tell us which, but
109 * this information is necessary to return the correct source line information.
110 *
111 * Thus we set this flag appropriately before we pass an event to
112 * the next ContentHandler, thereby making it possible to figure
113 * out which location to return.
114 */
115 private boolean inStart = false;
116
117 public void setDocumentLocator(Locator locator) {
118 // ignore one set by the parent.
119
120 super.setDocumentLocator(this);
121 }
122
123 public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
124 inStart = false;
125 super.endElement(namespaceURI, localName, qName);
126 }
127
128 public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
129 throws SAXException {
130 inStart = true;
131 super.startElement(namespaceURI, localName, qName, atts);
132 }
133
134
135
136
137 private Locator findLocator() {
138 Node n = parent.getCurrentLocation();
139 if( n instanceof Element ) {
140 Element e = (Element)n;
141 if( inStart )
142 return forest.locatorTable.getStartLocation( e );
143 else
144 return forest.locatorTable.getEndLocation( e );
145 }
146 return null;
147 }
148
149 //
150 //
151 // Locator methods
152 //
153 //
154 public int getColumnNumber() {
155 Locator l = findLocator();
156 if(l!=null) return l.getColumnNumber();
157 return -1;
158 }
159
160 public int getLineNumber() {
161 Locator l = findLocator();
162 if(l!=null) return l.getLineNumber();
163 return -1;
164 }
165
166 public String getPublicId() {
167 Locator l = findLocator();
168 if(l!=null) return l.getPublicId();
169 return null;
170 }
171
172 public String getSystemId() {
173 Locator l = findLocator();
174 if(l!=null) return l.getSystemId();
175 return null;
176 }
177
178 }
179 }