KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > util > location > LocationAttributes


1 /*
2  * Copyright 2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.util.location;
17
18 import org.w3c.dom.Attr JavaDoc;
19 import org.w3c.dom.Element JavaDoc;
20 import org.w3c.dom.Node JavaDoc;
21 import org.w3c.dom.NodeList JavaDoc;
22 import org.xml.sax.Attributes JavaDoc;
23 import org.xml.sax.ContentHandler JavaDoc;
24 import org.xml.sax.Locator JavaDoc;
25 import org.xml.sax.SAXException JavaDoc;
26 import org.xml.sax.helpers.AttributesImpl JavaDoc;
27
28 /**
29  * A class to handle location information stored in attributes.
30  * These attributes are typically setup using {@link org.apache.cocoon.util.location.LocationAttributes.Pipe}
31  * which augments the SAX stream with additional attributes, e.g.:
32  * <pre>
33  * &lt;root xmlns:loc="http://apache.org/cocoon/location"
34  * loc:src="file://path/to/file.xml"
35  * loc:line="1" loc:column="1"&gt;
36  * &lt;foo loc:src="file://path/to/file.xml" loc:line="2" loc:column="3"/&gt;
37  * &lt;/root&gt;
38  * </pre>
39  *
40  * @see org.apache.cocoon.util.location.LocationAttributes.Pipe
41  * @since 2.1.8
42  * @version $Id: LocationAttributes.java 328353 2005-10-25 12:59:42Z sylvain $
43  */

44 public class LocationAttributes {
45     /** Prefix for the location namespace */
46     public static final String JavaDoc PREFIX = "loc";
47     /** Namespace URI for location attributes */
48     public static final String JavaDoc URI = "http://apache.org/cocoon/location";
49
50     /** Attribute name for the location URI */
51     public static final String JavaDoc SRC_ATTR = "src";
52     /** Attribute name for the line number */
53     public static final String JavaDoc LINE_ATTR = "line";
54     /** Attribute name for the column number */
55     public static final String JavaDoc COL_ATTR = "column";
56
57     /** Attribute qualified name for the location URI */
58     public static final String JavaDoc Q_SRC_ATTR = "loc:src";
59     /** Attribute qualified name for the line number */
60     public static final String JavaDoc Q_LINE_ATTR = "loc:line";
61     /** Attribute qualified name for the column number */
62     public static final String JavaDoc Q_COL_ATTR = "loc:column";
63     
64     // Private constructor, we only have static methods
65
private LocationAttributes() {
66         // Nothing
67
}
68     
69     /**
70      * Add location attributes to a set of SAX attributes.
71      *
72      * @param locator the <code>Locator</code> (can be null)
73      * @param attrs the <code>Attributes</code> where locator information should be added
74      * @return
75      */

76     public static Attributes JavaDoc addLocationAttributes(Locator JavaDoc locator, Attributes JavaDoc attrs) {
77         if (locator == null || attrs.getIndex(URI, SRC_ATTR) != -1) {
78             // No location information known, or already has it
79
return attrs;
80         }
81         
82         // Get an AttributeImpl so that we can add new attributes.
83
AttributesImpl JavaDoc newAttrs = attrs instanceof AttributesImpl JavaDoc ?
84             (AttributesImpl JavaDoc)attrs : new AttributesImpl JavaDoc(attrs);
85
86         newAttrs.addAttribute(URI, SRC_ATTR, Q_SRC_ATTR, "CDATA", locator.getSystemId());
87         newAttrs.addAttribute(URI, LINE_ATTR, Q_LINE_ATTR, "CDATA", Integer.toString(locator.getLineNumber()));
88         newAttrs.addAttribute(URI, COL_ATTR, Q_COL_ATTR, "CDATA", Integer.toString(locator.getColumnNumber()));
89         
90         return newAttrs;
91     }
92     
93     /**
94      * Returns the {@link Location} of an element (SAX flavor).
95      *
96      * @param attrs the element's attributes that hold the location information
97      * @param description a description for the location (can be null)
98      * @return a {@link Location} object
99      */

100     public static Location getLocation(Attributes JavaDoc attrs, String JavaDoc description) {
101         String JavaDoc src = attrs.getValue(URI, SRC_ATTR);
102         if (src == null) {
103             return Location.UNKNOWN;
104         }
105         
106         return new LocationImpl(description, src, getLine(attrs), getColumn(attrs));
107     }
108
109     /**
110      * Returns the location of an element (SAX flavor). If the location is to be kept
111      * into an object built from this element, consider using {@link #getLocation(Attributes)}
112      * and the {@link Locatable} interface.
113      *
114      * @param attrs the element's attributes that hold the location information
115      * @return a location string as defined by {@link Location#toString()}.
116      */

117     public static String JavaDoc getLocationString(Attributes JavaDoc attrs) {
118         String JavaDoc src = attrs.getValue(URI, SRC_ATTR);
119         if (src == null) {
120             return LocationUtils.UNKNOWN_STRING;
121         }
122         
123         return src + ":" + attrs.getValue(URI, LINE_ATTR) + ":" + attrs.getValue(URI, COL_ATTR);
124     }
125     
126     /**
127      * Returns the URI of an element (SAX flavor)
128      *
129      * @param attrs the element's attributes that hold the location information
130      * @return the element's URI or "<code>[unknown location]</code>" if <code>attrs</code>
131      * has no location information.
132      */

133     public static String JavaDoc getURI(Attributes JavaDoc attrs) {
134         String JavaDoc src = attrs.getValue(URI, SRC_ATTR);
135         return src != null ? src : LocationUtils.UNKNOWN_STRING;
136     }
137     
138     /**
139      * Returns the line number of an element (SAX flavor)
140      *
141      * @param attrs the element's attributes that hold the location information
142      * @return the element's line number or <code>-1</code> if <code>attrs</code>
143      * has no location information.
144      */

145     public static int getLine(Attributes JavaDoc attrs) {
146         String JavaDoc line = attrs.getValue(URI, LINE_ATTR);
147         return line != null ? Integer.parseInt(line) : -1;
148     }
149     
150     /**
151      * Returns the column number of an element (SAX flavor)
152      *
153      * @param attrs the element's attributes that hold the location information
154      * @return the element's column number or <code>-1</code> if <code>attrs</code>
155      * has no location information.
156      */

157     public static int getColumn(Attributes JavaDoc attrs) {
158         String JavaDoc col = attrs.getValue(URI, COL_ATTR);
159         return col != null ? Integer.parseInt(col) : -1;
160     }
161     
162     /**
163      * Returns the {@link Location} of an element (DOM flavor).
164      *
165      * @param attrs the element that holds the location information
166      * @param description a description for the location (if <code>null</code>, the element's name is used)
167      * @return a {@link Location} object
168      */

169     public static Location getLocation(Element JavaDoc elem, String JavaDoc description) {
170         Attr JavaDoc srcAttr = elem.getAttributeNodeNS(URI, SRC_ATTR);
171         if (srcAttr == null) {
172             return Location.UNKNOWN;
173         }
174
175         return new LocationImpl(description == null ? elem.getNodeName() : description,
176                 srcAttr.getValue(), getLine(elem), getColumn(elem));
177     }
178     
179     /**
180      * Same as <code>getLocation(elem, null)</code>.
181      */

182     public static Location getLocation(Element JavaDoc elem) {
183         return getLocation(elem, null);
184     }
185    
186
187     /**
188      * Returns the location of an element that has been processed by this pipe (DOM flavor).
189      * If the location is to be kept into an object built from this element, consider using
190      * {@link #getLocation(Element)} and the {@link Locatable} interface.
191      *
192      * @param elem the element that holds the location information
193      * @return a location string as defined by {@link Location#toString()}.
194      */

195     public static String JavaDoc getLocationString(Element JavaDoc elem) {
196         Attr JavaDoc srcAttr = elem.getAttributeNodeNS(URI, SRC_ATTR);
197         if (srcAttr == null) {
198             return LocationUtils.UNKNOWN_STRING;
199         }
200         
201         return srcAttr.getValue() + ":" + elem.getAttributeNS(URI, LINE_ATTR) + ":" + elem.getAttributeNS(URI, COL_ATTR);
202     }
203     
204     /**
205      * Returns the URI of an element (DOM flavor)
206      *
207      * @param elem the element that holds the location information
208      * @return the element's URI or "<code>[unknown location]</code>" if <code>elem</code>
209      * has no location information.
210      */

211     public static String JavaDoc getURI(Element JavaDoc elem) {
212         Attr JavaDoc attr = elem.getAttributeNodeNS(URI, SRC_ATTR);
213         return attr != null ? attr.getValue() : LocationUtils.UNKNOWN_STRING;
214     }
215
216     /**
217      * Returns the line number of an element (DOM flavor)
218      *
219      * @param elem the element that holds the location information
220      * @return the element's line number or <code>-1</code> if <code>elem</code>
221      * has no location information.
222      */

223     public static int getLine(Element JavaDoc elem) {
224         Attr JavaDoc attr = elem.getAttributeNodeNS(URI, LINE_ATTR);
225         return attr != null ? Integer.parseInt(attr.getValue()) : -1;
226     }
227
228     /**
229      * Returns the column number of an element (DOM flavor)
230      *
231      * @param elem the element that holds the location information
232      * @return the element's column number or <code>-1</code> if <code>elem</code>
233      * has no location information.
234      */

235     public static int getColumn(Element JavaDoc elem) {
236         Attr JavaDoc attr = elem.getAttributeNodeNS(URI, COL_ATTR);
237         return attr != null ? Integer.parseInt(attr.getValue()) : -1;
238     }
239     
240     /**
241      * Remove the location attributes from a DOM element.
242      *
243      * @param elem the element to remove the location attributes from.
244      * @param recurse if <code>true</code>, also remove location attributes on descendant elements.
245      */

246     public static void remove(Element JavaDoc elem, boolean recurse) {
247         elem.removeAttributeNS(URI, SRC_ATTR);
248         elem.removeAttributeNS(URI, LINE_ATTR);
249         elem.removeAttributeNS(URI, COL_ATTR);
250         if (recurse) {
251             NodeList JavaDoc children = elem.getChildNodes();
252             for (int i = 0; i < children.getLength(); i++) {
253                 Node JavaDoc child = children.item(i);
254                 if (child.getNodeType() == Node.ELEMENT_NODE) {
255                     remove((Element JavaDoc)child, recurse);
256                 }
257             }
258         }
259     }
260
261     /**
262      * A SAX filter that adds the information available from the <code>Locator</code> as attributes.
263      * The purpose of having location as attributes is to allow this information to survive transformations
264      * of the document (an XSL could copy these attributes over) or conversion of SAX events to a DOM.
265      * <p>
266      * The location is added as 3 attributes in a specific namespace to each element.
267      * <pre>
268      * &lt;root xmlns:loc="http://apache.org/cocoon/location"
269      * loc:src="file://path/to/file.xml"
270      * loc:line="1" loc:column="1"&gt;
271      * &lt;foo loc:src="file://path/to/file.xml" loc:line="2" loc:column="3"/&gt;
272      * &lt;/root&gt;
273      * </pre>
274      * <strong>Note:</strong> Although this adds a lot of information to the serialized form of the document,
275      * the overhead in SAX events is not that big, as attribute names are interned, and all <code>src</code>
276      * attributes point to the same string.
277      *
278      * @see org.apache.cocoon.util.location.LocationAttributes
279      * @since 2.1.8
280      */

281     public static class Pipe implements ContentHandler JavaDoc {
282         
283         private Locator JavaDoc locator;
284         
285         private ContentHandler JavaDoc nextHandler;
286         
287         /**
288          * Create a filter. It has to be chained to another handler to be really useful.
289          */

290         public Pipe() {
291         }
292
293         /**
294          * Create a filter that is chained to another handler.
295          * @param next the next handler in the chain.
296          */

297         public Pipe(ContentHandler JavaDoc next) {
298             nextHandler = next;
299         }
300
301         public void setDocumentLocator(Locator JavaDoc locator) {
302             this.locator = locator;
303             nextHandler.setDocumentLocator(locator);
304         }
305         
306         public void startDocument() throws SAXException JavaDoc {
307             nextHandler.startDocument();
308             nextHandler.startPrefixMapping(LocationAttributes.PREFIX, LocationAttributes.URI);
309         }
310         
311         public void endDocument() throws SAXException JavaDoc {
312             endPrefixMapping(LocationAttributes.PREFIX);
313             nextHandler.endDocument();
314         }
315
316         public void startElement(String JavaDoc uri, String JavaDoc loc, String JavaDoc raw, Attributes JavaDoc attrs) throws SAXException JavaDoc {
317             // Add location attributes to the element
318
nextHandler.startElement(uri, loc, raw, LocationAttributes.addLocationAttributes(locator, attrs));
319         }
320
321         public void endElement(String JavaDoc arg0, String JavaDoc arg1, String JavaDoc arg2) throws SAXException JavaDoc {
322             nextHandler.endElement(arg0, arg1, arg2);
323         }
324
325         public void startPrefixMapping(String JavaDoc arg0, String JavaDoc arg1) throws SAXException JavaDoc {
326             nextHandler.startPrefixMapping(arg0, arg1);
327         }
328
329         public void endPrefixMapping(String JavaDoc arg0) throws SAXException JavaDoc {
330             nextHandler.endPrefixMapping(arg0);
331         }
332
333         public void characters(char[] arg0, int arg1, int arg2) throws SAXException JavaDoc {
334             nextHandler.characters(arg0, arg1, arg2);
335         }
336
337         public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException JavaDoc {
338             nextHandler.ignorableWhitespace(arg0, arg1, arg2);
339         }
340
341         public void processingInstruction(String JavaDoc arg0, String JavaDoc arg1) throws SAXException JavaDoc {
342             nextHandler.processingInstruction(arg0, arg1);
343         }
344
345         public void skippedEntity(String JavaDoc arg0) throws SAXException JavaDoc {
346             nextHandler.skippedEntity(arg0);
347         }
348     }
349 }
350
Popular Tags