001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036: package com.sun.tools.xjc.reader.internalizer;
037:
038: import com.sun.xml.bind.unmarshaller.DOMScanner;
039:
040: import org.w3c.dom.Document;
041: import org.w3c.dom.Element;
042: import org.w3c.dom.Node;
043: import org.xml.sax.Attributes;
044: import org.xml.sax.ContentHandler;
045: import org.xml.sax.Locator;
046: import org.xml.sax.SAXException;
047: import org.xml.sax.helpers.XMLFilterImpl;
048:
049: /**
050: * Produces a complete series of SAX events from any DOM node
051: * in the DOMForest.
052: *
053: * <p>
054: * This class hides a logic of re-associating {@link Locator}
055: * to the generated SAX event stream.
056: *
057: * @author
058: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
059: */
060: public class DOMForestScanner {
061:
062: private final DOMForest forest;
063:
064: /**
065: * Scans DOM nodes of the given forest.
066: *
067: * DOM node parameters to the scan method must be a part of
068: * this forest.
069: */
070: public DOMForestScanner(DOMForest _forest) {
071: this .forest = _forest;
072: }
073:
074: /**
075: * Generates the whole set of SAX events by treating
076: * element e as if it's a root element.
077: */
078: public void scan(Element e, ContentHandler contentHandler)
079: throws SAXException {
080: DOMScanner scanner = new DOMScanner();
081:
082: // insert the location resolver into the pipe line
083: LocationResolver resolver = new LocationResolver(scanner);
084: resolver.setContentHandler(contentHandler);
085:
086: // parse this DOM.
087: scanner.setContentHandler(resolver);
088: scanner.scan(e);
089: }
090:
091: /**
092: * Generates the whole set of SAX events from the given Document
093: * in the DOMForest.
094: */
095: public void scan(Document d, ContentHandler contentHandler)
096: throws SAXException {
097: scan(d.getDocumentElement(), contentHandler);
098: }
099:
100: /**
101: * Intercepts the invocation of the setDocumentLocator method
102: * and passes itself as the locator.
103: *
104: * If the client calls one of the methods on the Locator interface,
105: * use the LocatorTable to resolve the source location.
106: */
107: private class LocationResolver extends XMLFilterImpl implements
108: Locator {
109: LocationResolver(DOMScanner _parent) {
110: this .parent = _parent;
111: }
112:
113: private final DOMScanner parent;
114:
115: /**
116: * Flag that tells us whether we are processing a start element event
117: * or an end element event.
118: *
119: * DOMScanner's getCurrentLocation method doesn't tell us which, but
120: * this information is necessary to return the correct source line information.
121: *
122: * Thus we set this flag appropriately before we pass an event to
123: * the next ContentHandler, thereby making it possible to figure
124: * out which location to return.
125: */
126: private boolean inStart = false;
127:
128: public void setDocumentLocator(Locator locator) {
129: // ignore one set by the parent.
130:
131: super .setDocumentLocator(this );
132: }
133:
134: public void endElement(String namespaceURI, String localName,
135: String qName) throws SAXException {
136: inStart = false;
137: super .endElement(namespaceURI, localName, qName);
138: }
139:
140: public void startElement(String namespaceURI, String localName,
141: String qName, Attributes atts) throws SAXException {
142: inStart = true;
143: super .startElement(namespaceURI, localName, qName, atts);
144: }
145:
146: private Locator findLocator() {
147: Node n = parent.getCurrentLocation();
148: if (n instanceof Element) {
149: Element e = (Element) n;
150: if (inStart)
151: return forest.locatorTable.getStartLocation(e);
152: else
153: return forest.locatorTable.getEndLocation(e);
154: }
155: return null;
156: }
157:
158: //
159: //
160: // Locator methods
161: //
162: //
163: public int getColumnNumber() {
164: Locator l = findLocator();
165: if (l != null)
166: return l.getColumnNumber();
167: return -1;
168: }
169:
170: public int getLineNumber() {
171: Locator l = findLocator();
172: if (l != null)
173: return l.getLineNumber();
174: return -1;
175: }
176:
177: public String getPublicId() {
178: Locator l = findLocator();
179: if (l != null)
180: return l.getPublicId();
181: return null;
182: }
183:
184: public String getSystemId() {
185: Locator l = findLocator();
186: if (l != null)
187: return l.getSystemId();
188: return null;
189: }
190:
191: }
192: }
|