PageRenderTime 15ms CodeModel.GetById 2ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/xml/namespaces/xmlns_tree.e

http://github.com/tybor/Liberty
Specman e | 326 lines | 263 code | 32 blank | 31 comment | 14 complexity | 3bc79f0012e444306cfa6e415a8185f1 MD5 | raw file
  1-- See the Copyright notice at the end of this file.
  2--
  3class XMLNS_TREE
  4   --
  5   -- DOM-like namespace-aware representation of an XML document
  6   --
  7   -- See also XMLNS_PARSER, XML_TREE
  8   --
  9
 10inherit
 11   XMLNS_CALLBACKS
 12
 13create {ANY}
 14   make, with_error_handler
 15
 16feature {ANY}
 17   root: XMLNS_COMPOSITE_NODE
 18         -- The root of the tree
 19
 20   attribute_at (a_attribute_name: UNICODE_STRING): UNICODE_STRING
 21         -- Usually to recover the "version" or "encoding" attributes
 22      do
 23         Result := tree_attributes.reference_at(a_attribute_name)
 24      end
 25
 26   set_processing_instruction (target: UNICODE_STRING; processor: PROCEDURE[TUPLE[UNICODE_STRING]])
 27      require
 28         target /= Void
 29         processor /= Void
 30      local
 31         processors: FAST_ARRAY[PROCEDURE[TUPLE[UNICODE_STRING]]]
 32      do
 33         processors := processing_instructions.reference_at(target)
 34         if processors = Void then
 35            create processors.make(0)
 36            processing_instructions.add(processors, target.twin)
 37         end
 38         processors.add_last(processor)
 39      end
 40
 41feature {}
 42   attributes: HASHED_DICTIONARY[HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING], UNICODE_STRING]
 43   no_namespace_attributes: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]
 44
 45   tree_attributes: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]
 46
 47   open_nodes: STACK[XMLNS_COMPOSITE_NODE]
 48
 49   processing_instructions: HASHED_DICTIONARY[FAST_ARRAY[PROCEDURE[TUPLE[UNICODE_STRING]]], UNICODE_STRING]
 50      once
 51         create Result.make
 52      end
 53
 54feature {XMLNS_PARSER}
 55   with_attribute (attribute_namespace, attribute_name: UNICODE_STRING; attribute_value: UNICODE_STRING; line, column: INTEGER)
 56      do
 57         attributes_for(attribute_namespace).put(attribute_value.twin, attribute_name.twin)
 58      end
 59
 60   open_node (node_namespace, node_name: UNICODE_STRING; line, column: INTEGER)
 61      local
 62         node: XMLNS_COMPOSITE_NODE; i, j: INTEGER; att: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]; ns: UNICODE_STRING
 63      do
 64         if node_namespace = Void then
 65            node := new_node(Void, node_name.twin, line, column)
 66         else
 67            node := new_node(node_namespace.twin, node_name.twin, line, column)
 68         end
 69         from
 70            i := attributes.lower
 71         until
 72            i > attributes.upper
 73         loop
 74            ns := attributes.key(i)
 75            att := attributes.item(i)
 76            from
 77               j := att.lower
 78            until
 79               j > att.upper
 80            loop
 81               node.set_attribute(ns, att.key(j), att.item(j))
 82               j := j + 1
 83            end
 84            i := i + 1
 85         end
 86         from
 87            j := no_namespace_attributes.lower
 88         until
 89            j > no_namespace_attributes.upper
 90         loop
 91            node.set_attribute(Void, no_namespace_attributes.key(j), no_namespace_attributes.item(j))
 92            j := j + 1
 93         end
 94         clear_attributes
 95         open_nodes.push(node)
 96      end
 97
 98   close_node (node_namespace, node_name: UNICODE_STRING; line, column: INTEGER)
 99      local
100         node: XMLNS_COMPOSITE_NODE
101      do
102         node := open_nodes.top
103         open_nodes.pop
104         if open_nodes.is_empty then
105            root := node
106         else
107            open_nodes.top.add_child(node)
108         end
109      end
110
111   open_close_node (node_namespace, node_name: UNICODE_STRING; line, column: INTEGER)
112      do
113         open_node(node_namespace, node_name, line, column)
114         close_node(node_namespace, node_name, line, column)
115      end
116
117   xml_header (line, column: INTEGER)
118      do
119         check
120            tree_attributes.is_empty
121         end
122         tree_attributes.copy(attributes_for(once U""))
123         clear_attributes
124      end
125
126   processing_instruction (a_target, a_data: UNICODE_STRING)
127      local
128         processors: FAST_ARRAY[PROCEDURE[TUPLE[UNICODE_STRING]]]; i: INTEGER
129      do
130         processors := processing_instructions.reference_at(a_target)
131         if processors /= Void then
132            from
133               i := processors.lower
134            until
135               i > processors.upper
136            loop
137               processors.item(i).call([a_data])
138               i := i + 1
139            end
140         end
141      end
142
143   current_node: UNICODE_STRING
144      do
145         if not open_nodes.is_empty then
146            Result := open_nodes.top.name
147         end
148      end
149
150   current_namespace: UNICODE_STRING
151      do
152         if not open_nodes.is_empty then
153            Result := open_nodes.top.namespace
154         end
155      end
156
157   entity (a_entity: UNICODE_STRING; line, column: INTEGER): UNICODE_STRING
158      do
159         -- The default tree does not recognize any other entity than XML defaults.
160      end
161
162   data (a_data: UNICODE_STRING; line, column: INTEGER)
163      local
164         d: XMLNS_DATA_NODE
165      do
166         create d.make(a_data.twin, line, column)
167         open_nodes.top.add_child(d)
168      end
169
170   parse_error (line, column: INTEGER; message: STRING)
171      do
172         at_error := True
173         if error_handler /= Void then
174            error_handler.call([line, column, message])
175         else
176            std_error.put_string(message)
177            std_error.put_string(" at line ")
178            std_error.put_integer(line)
179            std_error.put_string(", column ")
180            std_error.put_integer(column)
181            std_error.put_new_line
182            die_with_code(1)
183         end
184      end
185
186   at_error: BOOLEAN
187
188feature {}
189   error_handler: PROCEDURE[TUPLE[INTEGER, INTEGER, STRING]]
190
191   make (url: URL)
192         -- read the xml tree at the given `url'
193      require
194         url.is_connected implies url.read
195      do
196         create attributes.make
197         create no_namespace_attributes.make
198         create tree_attributes.make
199         create open_nodes.make
200         parser.connect_to(url)
201         parser.parse(Current)
202         parser.disconnect
203      end
204
205   with_error_handler (url: URL; a_error_handler: like error_handler)
206      do
207         error_handler := a_error_handler
208         make(url)
209      end
210
211   new_node (node_namespace, node_name: UNICODE_STRING; line, column: INTEGER): XMLNS_COMPOSITE_NODE
212      do
213         create Result.make(node_namespace, node_name, line, column)
214      end
215
216   parser: XMLNS_PARSER
217      once
218         create Result.make
219      end
220
221feature {} -- Memory management
222   unused_attributes: FAST_ARRAY[WEAK_REFERENCE[HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]]]
223      once
224         create Result.make(0)
225      end
226
227   new_attributes: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]
228      local
229         i: INTEGER
230      do
231         from
232            i := unused_attributes.upper
233         until
234            Result /= Void or else i < unused_attributes.lower
235         loop
236            Result := unused_attributes.item(i).item
237            i := i - 1
238         end
239         if Result = Void then
240            create Result.make
241         else
242            Result.clear_count
243         end
244      ensure
245         Result.is_empty
246      end
247
248   old_attributes (a_attributes: HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING])
249      local
250         i: INTEGER; done: BOOLEAN; wr: WEAK_REFERENCE[HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]]
251      do
252         from
253            i := unused_attributes.lower
254         until
255            done or else i > unused_attributes.upper
256         loop
257            wr := unused_attributes.item(i)
258            if wr.item = Void then
259               wr.set_item(a_attributes)
260               done := True
261            end
262            i := i + 1
263         end
264         if not done then
265            create wr.set_item(a_attributes)
266            unused_attributes.add_last(wr)
267         end
268      end
269
270   attributes_for (namespace: UNICODE_STRING): HASHED_DICTIONARY[UNICODE_STRING, UNICODE_STRING]
271      do
272         if namespace = Void then
273            Result := no_namespace_attributes
274         else
275            Result := attributes.reference_at(namespace)
276            if Result = Void then
277               Result := new_attributes
278               attributes.add(Result, namespace.twin)
279            end
280         end
281      ensure
282         Result /= Void
283         namespace /= Void implies attributes.fast_occurrences(Result) = 1
284         namespace = Void implies Result = no_namespace_attributes
285      end
286
287   clear_attributes
288      local
289         i: INTEGER
290      do
291         from
292            i := attributes.lower
293         until
294            i > attributes.upper
295         loop
296            old_attributes(attributes.item(i))
297            i := i + 1
298         end
299         attributes.clear_count
300         no_namespace_attributes.clear_count
301      ensure
302         attributes.is_empty
303         no_namespace_attributes.is_empty
304      end
305
306end -- class XMLNS_TREE
307--
308-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
309--
310-- Permission is hereby granted, free of charge, to any person obtaining a copy
311-- of this software and associated documentation files (the "Software"), to deal
312-- in the Software without restriction, including without limitation the rights
313-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
314-- copies of the Software, and to permit persons to whom the Software is
315-- furnished to do so, subject to the following conditions:
316--
317-- The above copyright notice and this permission notice shall be included in
318-- all copies or substantial portions of the Software.
319--
320-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
321-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
322-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
323-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
324-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
325-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
326-- THE SOFTWARE.