Merge: More keep going
[nit.git] / lib / sax / helpers / xml_filter_impl.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
9 # another product.
10
11 # Base class for deriving an XML filter.
12 module sax::helpers::xml_filter_impl
13
14 import sax::xml_reader
15 import sax::xml_filter
16 import sax::input_source
17 import sax::sax_locator
18 import sax::attributes
19 import sax::entity_resolver
20 import sax::dtd_handler
21 import sax::content_handler
22 import sax::error_handler
23 import sax::sax_parse_exception
24
25 # Base class for deriving an XML filter.
26 #
27 # This class is designed to sit between an `XMLReader`
28 # and the client application's event handlers. By default, it
29 # does nothing but pass requests up to the reader and events
30 # on to the handlers unmodified, but subclasses can override
31 # specific methods to modify the event stream or the configuration
32 # requests as they pass through.
33 #
34 # Note: The original source code and documentation of this class comes, in part,
35 # from [SAX 2.0](http://www.saxproject.org).
36 class XMLFilterImpl
37 super XMLFilter
38 super EntityResolver
39 super DTDHandler
40 super ContentHandler
41 super ErrorHandler
42
43 # XMLFilter
44
45 redef var parent = null is writable
46
47 # XMLReader
48
49 redef var entity_resolver = null is writable
50 redef var dtd_handler = null is writable
51 redef var content_handler = null is writable
52 redef var error_handler = null is writable
53
54
55 ############################################################################
56 # XMLReader
57
58 # Construct an empty XML filter, with no parent.
59 #
60 # This filter will have no parent: you must assign a parent
61 # before you start a parse or do any configuration with
62 # `feature=` or `property=`, unless you use this as
63 # a pure event consumer rather than as an `XMLReader`.
64 #
65 # SEE: `parent`
66 init do
67 end
68
69 # Construct an XML filter with the specified parent.
70 #
71 # SEE: `parent`
72 init with_parent(parent_reader: XMLReader) do
73 parent = parent_reader
74 end
75
76 redef fun feature_recognized(name) do
77 if parent == null then
78 return false
79 else
80 return parent.feature_recognized(name)
81 end
82 end
83
84 redef fun feature_readable(name) do
85 if parent == null then
86 return false
87 else
88 return parent.feature_readable(name)
89 end
90 end
91
92 redef fun feature_writable(name) do
93 if parent == null then
94 return false
95 else
96 return parent.feature_writable(name)
97 end
98 end
99
100 # Look up the value of a feature.
101 #
102 # This will always fail if the parent is `null`.
103 #
104 # Parameters:
105 #
106 # * `name`: The feature name.
107 #
108 # Returns:
109 #
110 # The current value of the feature.
111 #
112 # SEE: `feature_recognized`
113 #
114 # SEE: `feature_readable`
115 redef fun feature(name) do
116 assert sax_recognized: parent != null else
117 sys.stderr.write("Feature: {name}\n")
118 end
119 return parent.feature(name)
120 end
121
122 # Set the value of a feature.
123 #
124 # This will always fail if the parent is `null`.
125 #
126 # Parameters:
127 #
128 # * `name`: feature name.
129 # * `value`: requested feature value.
130 #
131 # Returns:
132 #
133 # `true` if the feature is set; `false` if the feature can not be set given
134 # the current context.
135 #
136 # SEE: `feature_recognized`
137 #
138 # SEE: `feature_writable`
139 redef fun feature=(name, value) do
140 assert sax_recognized: parent != null else
141 sys.stderr.write("Feature: {name}\n")
142 end
143 parent.feature(name) = value
144 end
145
146 redef fun property_recognized(name) do
147 if parent == null then
148 return false
149 else
150 return parent.property_recognized(name)
151 end
152 end
153
154 redef fun property_readable(name) do
155 if parent == null then
156 return false
157 else
158 return parent.property_readable(name)
159 end
160 end
161
162 redef fun property_writable(name) do
163 if parent == null then
164 return false
165 else
166 return parent.property_writable(name)
167 end
168 end
169
170 # Look up the value of a property.
171 #
172 # Parameters:
173 #
174 # * `name`: The property name.
175 #
176 # Returns:
177 #
178 # The current value of the property.
179 #
180 # SEE: `property_recognized`
181 #
182 # SEE: `property_readable`
183 redef fun property(name) do
184 assert sax_recognized: parent != null else
185 sys.stderr.write("Property: {name}\n")
186 end
187 return parent.property(name)
188 end
189
190 # Set the value of a property.
191 #
192 # This will always fail if the parent is `null`.
193 #
194 # Parameters:
195 #
196 # * `name`: property name.
197 # * `value`: requested feature value.
198 #
199 # Returns:
200 #
201 # `true` if the property is set; `false` if the property can not be set
202 # given the current context.
203 #
204 # SEE: `property_recognized`
205 #
206 # SEE: `property_writable`
207 redef fun property=(name, value) do
208 assert sax_recognized: parent != null else
209 sys.stderr.write("Property: {name}\n")
210 end
211 parent.property(name) = value
212 end
213
214 redef fun parse(input) do
215 setup_parse
216 parent.parse(input)
217 end
218
219 redef fun parse_file(system_id) do
220 var source = new InputSource
221
222 source.system_id = system_id
223 parse(source)
224 end
225
226
227 ############################################################################
228 # EntityResolver
229
230 redef fun resolve_entity(public_id, system_id) do
231 if entity_resolver == null then
232 return null
233 else
234 return entity_resolver.resolve_entity(public_id, system_id)
235 end
236 end
237
238
239 ############################################################################
240 # DTDHandler
241
242 redef fun notation_decl(name, public_id, system_id) do
243 if dtd_handler != null then
244 dtd_handler.notation_decl(name, public_id, system_id)
245 end
246 end
247
248 redef fun unparsed_entity_decl(name, public_id, system_id) do
249 if dtd_handler != null then
250 dtd_handler.unparsed_entity_decl(name, public_id, system_id)
251 end
252 end
253
254
255 ############################################################################
256 # ContentHandler
257
258 redef fun document_locator=(locator) do
259 if content_handler != null then
260 content_handler.document_locator = locator
261 end
262 end
263
264 redef fun start_document do
265 if content_handler != null then
266 content_handler.start_document
267 end
268 end
269
270 redef fun end_document do
271 if content_handler != null then
272 content_handler.end_document
273 end
274 end
275
276 redef fun start_prefix_mapping(prefix, uri) do
277 if content_handler != null then
278 content_handler.start_prefix_mapping(prefix, uri)
279 end
280 end
281
282 redef fun end_prefix_mapping(prefix) do
283 if content_handler != null then
284 content_handler.end_prefix_mapping(prefix)
285 end
286 end
287
288 redef fun start_element(uri, local_name, qname, atts) do
289 if content_handler != null then
290 content_handler.start_element(uri, local_name, qname, atts)
291 end
292 end
293
294 redef fun end_element(uri, local_name, qname) do
295 if content_handler != null then
296 content_handler.end_element(uri, local_name, qname)
297 end
298 end
299
300 redef fun characters(str) do
301 if content_handler != null then
302 content_handler.characters(str)
303 end
304 end
305
306 redef fun ignorable_whitespace(str) do
307 if content_handler != null then
308 content_handler.ignorable_whitespace(str)
309 end
310 end
311
312 redef fun processing_instruction(target, data) do
313 if content_handler != null then
314 content_handler.processing_instruction(target, data)
315 end
316 end
317
318 redef fun skipped_entity(name) do
319 if content_handler != null then
320 content_handler.skipped_entity(name)
321 end
322 end
323
324
325 ############################################################################
326 # ErrorHandler
327
328 redef fun warning(exception) do
329 if error_handler != null then
330 error_handler.warning(exception)
331 end
332 end
333
334 redef fun error(exception) do
335 if error_handler != null then
336 error_handler.error(exception)
337 end
338 end
339
340 redef fun fatal_error(exception) do
341 if error_handler != null then
342 error_handler.fatal_error(exception)
343 else
344 exception.throw
345 end
346 end
347
348 ############################################################################
349 # private
350
351 # Set up before a parse.
352 #
353 # Before every parse, check whether the parent is
354 # non-null, and re-register the filter for all of the
355 # events.
356 private fun setup_parse do
357 assert parent_is_not_null: parent != 0 else
358 sys.stderr.write("No parent for filter.")
359 end
360 parent.entity_resolver = self
361 parent.dtd_handler = self
362 parent.content_handler = self
363 parent.error_handler = self
364 end
365 end