001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.internal.xjc.reader.internalizer;
027:
028: import com.sun.xml.internal.bind.unmarshaller.DOMScanner;
029:
030: import org.w3c.dom.Document;
031: import org.w3c.dom.Element;
032: import org.w3c.dom.Node;
033: import org.xml.sax.Attributes;
034: import org.xml.sax.ContentHandler;
035: import org.xml.sax.Locator;
036: import org.xml.sax.SAXException;
037: import org.xml.sax.helpers.XMLFilterImpl;
038:
039: /**
040: * Produces a complete series of SAX events from any DOM node
041: * in the DOMForest.
042: *
043: * <p>
044: * This class hides a logic of re-associating {@link Locator}
045: * to the generated SAX event stream.
046: *
047: * @author
048: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
049: */
050: public class DOMForestScanner {
051:
052: private final DOMForest forest;
053:
054: /**
055: * Scans DOM nodes of the given forest.
056: *
057: * DOM node parameters to the scan method must be a part of
058: * this forest.
059: */
060: public DOMForestScanner(DOMForest _forest) {
061: this .forest = _forest;
062: }
063:
064: /**
065: * Generates the whole set of SAX events by treating
066: * element e as if it's a root element.
067: */
068: public void scan(Element e, ContentHandler contentHandler)
069: throws SAXException {
070: DOMScanner scanner = new DOMScanner();
071:
072: // insert the location resolver into the pipe line
073: LocationResolver resolver = new LocationResolver(scanner);
074: resolver.setContentHandler(contentHandler);
075:
076: // parse this DOM.
077: scanner.setContentHandler(resolver);
078: scanner.scan(e);
079: }
080:
081: /**
082: * Generates the whole set of SAX events from the given Document
083: * in the DOMForest.
084: */
085: public void scan(Document d, ContentHandler contentHandler)
086: throws SAXException {
087: scan(d.getDocumentElement(), contentHandler);
088: }
089:
090: /**
091: * Intercepts the invocation of the setDocumentLocator method
092: * and passes itself as the locator.
093: *
094: * If the client calls one of the methods on the Locator interface,
095: * use the LocatorTable to resolve the source location.
096: */
097: private class LocationResolver extends XMLFilterImpl implements
098: Locator {
099: LocationResolver(DOMScanner _parent) {
100: this .parent = _parent;
101: }
102:
103: private final DOMScanner parent;
104:
105: /**
106: * Flag that tells us whether we are processing a start element event
107: * or an end element event.
108: *
109: * DOMScanner's getCurrentLocation method doesn't tell us which, but
110: * this information is necessary to return the correct source line information.
111: *
112: * Thus we set this flag appropriately before we pass an event to
113: * the next ContentHandler, thereby making it possible to figure
114: * out which location to return.
115: */
116: private boolean inStart = false;
117:
118: public void setDocumentLocator(Locator locator) {
119: // ignore one set by the parent.
120:
121: super .setDocumentLocator(this );
122: }
123:
124: public void endElement(String namespaceURI, String localName,
125: String qName) throws SAXException {
126: inStart = false;
127: super .endElement(namespaceURI, localName, qName);
128: }
129:
130: public void startElement(String namespaceURI, String localName,
131: String qName, Attributes atts) throws SAXException {
132: inStart = true;
133: super .startElement(namespaceURI, localName, qName, atts);
134: }
135:
136: private Locator findLocator() {
137: Node n = parent.getCurrentLocation();
138: if (n instanceof Element) {
139: Element e = (Element) n;
140: if (inStart)
141: return forest.locatorTable.getStartLocation(e);
142: else
143: return forest.locatorTable.getEndLocation(e);
144: }
145: return null;
146: }
147:
148: //
149: //
150: // Locator methods
151: //
152: //
153: public int getColumnNumber() {
154: Locator l = findLocator();
155: if (l != null)
156: return l.getColumnNumber();
157: return -1;
158: }
159:
160: public int getLineNumber() {
161: Locator l = findLocator();
162: if (l != null)
163: return l.getLineNumber();
164: return -1;
165: }
166:
167: public String getPublicId() {
168: Locator l = findLocator();
169: if (l != null)
170: return l.getPublicId();
171: return null;
172: }
173:
174: public String getSystemId() {
175: Locator l = findLocator();
176: if (l != null)
177: return l.getSystemId();
178: return null;
179: }
180:
181: }
182: }
|