PageRenderTime 17ms CodeModel.GetById 12ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 1ms

/src/lib/xml/dtd/xml_dtd_element.e

http://github.com/tybor/Liberty
Specman e | 528 lines | 425 code | 66 blank | 37 comment | 5 complexity | 618fd58bf4803e6309cd21f3ba1b757d MD5 | raw file
  1-- See the Copyright notice at the end of this file.
  2--
  3class XML_DTD_ELEMENT
  4   --
  5   -- Static description of a DTD element: structure (nested elements), attributes, data
  6   --
  7
  8inherit
  9   BACKTRACKING_NODE
 10      undefine
 11         fill_tagged_out_memory
 12      end
 13
 14insert
 15   BACKTRACKING_NODE_FILL
 16   RECYCLABLE
 17      undefine
 18         fill_tagged_out_memory
 19      end
 20
 21create {XML_DTD_VALIDATOR}
 22   make
 23
 24feature {ANY}
 25   name: UNICODE_STRING
 26
 27feature {XML_DTD_VALIDATOR}
 28   build
 29         -- Prepare to build the element's structure
 30      do
 31         -- remove crumbs from a possibly failed previous build
 32         building_stack.clear_count
 33      end
 34
 35feature {XML_DTD_VALIDATOR, XML_DTD_NODE}
 36   is_built: BOOLEAN
 37
 38feature {XML_DTD_VALIDATOR} -- Data validation
 39   is_valid_attributes (xml_attributes: DICTIONARY[UNICODE_STRING, UNICODE_STRING]): BOOLEAN
 40      local
 41         i: INTEGER
 42      do
 43         from
 44            Result := True
 45            i := attributes.lower
 46         until
 47            not Result or else i > attributes.upper
 48         loop
 49            Result := attributes.item(i).is_valid(xml_attributes)
 50            i := i + 1
 51         end
 52      end
 53
 54feature {XML_DTD_NODE} -- Tree validation
 55   is_valid_child (explorer: XML_DTD_VALIDATOR; node_name: UNICODE_STRING; children: FAST_ARRAY[XML_DTD_NODE]): BOOLEAN
 56      require
 57         explorer /= Void
 58         children /= Void
 59         is_built
 60      do
 61         Result := explorer.backtrack_is_valid(children, structure, node_name)
 62         if not Result then
 63            sedb_breakpoint
 64         end
 65      end
 66
 67   is_valid_data (explorer: XML_DTD_VALIDATOR; data: UNICODE_STRING; children: FAST_ARRAY[XML_DTD_NODE]): BOOLEAN
 68      require
 69         explorer /= Void
 70         children /= Void
 71         is_built
 72      do
 73         Result := explorer.backtrack_valid_data(children, structure, data)
 74      end
 75
 76feature {ANY} -- Tree structure validation
 77   explore (explorer: XML_DTD_VALIDATOR)
 78      do
 79         explorer.backtrack_valid_child(Current)
 80      end
 81
 82feature {} -- The element's structure
 83   structure: BACKTRACKING_NODE
 84         -- the element's structure
 85
 86   building_stack: FAST_ARRAY[BACKTRACKING_NODE]
 87         -- Used when building the element. A once object is enough since we only build one element at a time.
 88      once
 89         create Result.make(0)
 90      end
 91
 92   build_pop
 93      do
 94         building_stack.remove_last
 95      end
 96
 97   build_add (a_node: BACKTRACKING_NODE)
 98      do
 99         building_stack.add_last(a_node)
100      end
101
102   build_set_top (a_node: BACKTRACKING_NODE)
103      do
104         building_stack.put(a_node, building_stack.upper)
105      ensure
106         build_top = a_node
107      end
108
109   build_top: BACKTRACKING_NODE
110      do
111         Result := building_stack.last
112      end
113
114feature {XML_DTD_VALIDATOR} -- Building element's structure
115   close_fix
116      do
117         check
118            building_stack.count = 1
119         end
120         structure := node_and_end(build_top)
121         building_stack.remove_last
122      ensure
123         building_stack.is_empty
124      end
125
126   close_exactly_one
127      do
128         build_set_top(node_and_end(build_top))
129      end
130
131   close_zero_or_one
132      do
133         build_set_top(zero_or_one_node(build_top))
134      end
135
136   close_zero_or_more
137      do
138         build_set_top(zero_or_more_node(build_top))
139      end
140
141   close_one_or_more
142      do
143         build_set_top(one_or_more_node(build_top))
144      end
145
146   add_list
147      require
148         building_stack.count > 1
149      local
150         l, r: BACKTRACKING_NODE; n: BACKTRACKING_NODE_AND_PAIR
151      do
152         r := build_top
153         build_pop
154         l := build_top
155         create n.make(l, r)
156         build_set_top(n)
157      ensure
158         building_stack.count = old building_stack.count - 1
159      end
160
161   add_alt
162      require
163         building_stack.count > 1
164      local
165         l, r: BACKTRACKING_NODE; n: BACKTRACKING_NODE_OR_PAIR
166      do
167         r := build_top
168         build_pop
169         l := build_top
170         create n.make(l, r)
171         build_set_top(n)
172      ensure
173         building_stack.count = old building_stack.count - 1
174      end
175
176   child_pcdata
177      do
178         build_add(pcdata_node)
179      end
180
181   child_any
182      do
183         build_add(any_node)
184      end
185
186   child_empty
187      do
188         build_add(empty_node)
189      end
190
191   child_one_or_more (elt: XML_DTD_ELEMENT)
192      do
193         build_add(one_or_more_node(elt))
194      end
195
196   child_zero_or_more (elt: XML_DTD_ELEMENT)
197      do
198         build_add(zero_or_more_node(elt))
199      end
200
201   child_zero_or_one (elt: XML_DTD_ELEMENT)
202      do
203         build_add(zero_or_one_node(elt))
204      end
205
206   child_exactly_one (elt: XML_DTD_ELEMENT)
207      do
208         build_add(node_and_end(elt))
209      end
210
211   commit
212      require
213         not is_built
214      do
215         check
216            structure /= Void
217         end
218         is_built := True
219      ensure
220         is_built
221      end
222
223feature {} -- Multiplicity helpers
224   one_or_more_node (a_node: BACKTRACKING_NODE): BACKTRACKING_NODE
225      local
226         a: BACKTRACKING_NODE_AND_PAIR; b: BACKTRACKING_NODE_OR_TRUE
227      do
228         create b.make(a_node) -- a
229         create a.make(a_node, b)
230         b.set_node(a)
231         Result := a
232      end
233
234   zero_or_more_node (a_node: BACKTRACKING_NODE): BACKTRACKING_NODE
235      local
236         a: BACKTRACKING_NODE_AND_PAIR; b: BACKTRACKING_NODE_OR_TRUE
237      do
238         create b.make(a_node) -- a
239         create a.make(a_node, b)
240         b.set_node(a)
241         Result := b
242      end
243
244   zero_or_one_node (a_node: BACKTRACKING_NODE): BACKTRACKING_NODE
245      do
246         create {BACKTRACKING_NODE_OR_TRUE} Result.make(a_node)
247      end
248
249   node_and_end (a_node: BACKTRACKING_NODE): BACKTRACKING_NODE
250      do
251         create {BACKTRACKING_NODE_AND_PAIR} Result.make(a_node, end_node)
252      end
253
254feature {} -- Special nodes
255   any_node: XML_DTD_ANY_NODE
256      once
257         create Result.make
258      end
259
260   empty_node: XML_DTD_EMPTY_NODE
261      once
262         create Result.make
263      end
264
265   end_node: XML_DTD_END_NODE
266      once
267         create Result.make
268      end
269
270   pcdata_node: XML_DTD_PCDATA_NODE
271      once
272         create Result.make
273      end
274
275feature {XML_DTD_VALIDATOR} -- Adding attributes
276   attributes: HASHED_DICTIONARY[XML_DTD_ATTRIBUTE, UNICODE_STRING]
277
278   current_attribute: XML_DTD_ATTRIBUTE
279
280   building_attlist: BOOLEAN
281      do
282         Result := current_attribute /= Void
283      end
284
285   adding_attlist (attribute_name: UNICODE_STRING): BOOLEAN
286      do
287         Result := current_attribute /= Void and then current_attribute.name.is_equal(attribute_name)
288      ensure
289         Result implies building_attlist
290      end
291
292   has_attlist (attribute_name: UNICODE_STRING): BOOLEAN
293      do
294         Result := attributes.has(attribute_name)
295      end
296
297   add_attlist (attribute_name: UNICODE_STRING)
298      require
299         not has_attlist(attribute_name)
300         not building_attlist
301      local
302         att: XML_DTD_ATTRIBUTE
303      do
304         if attributes_pool.is_empty then
305            create att.make(attribute_name)
306         else
307            att := attributes_pool.item
308            att.make(attribute_name)
309         end
310         current_attribute := att
311      ensure
312         building_attlist
313      end
314
315   commit_attlist (attribute_name: UNICODE_STRING)
316      require
317         adding_attlist(attribute_name)
318      do
319         attributes.add(current_attribute, current_attribute.name)
320         current_attribute := Void
321      ensure
322         not building_attlist
323      end
324
325   attlist_list_value (value: UNICODE_STRING)
326      require
327         building_attlist
328      do
329         current_attribute.list_value(value)
330      end
331
332   attlist_cdata
333      require
334         building_attlist
335      do
336         current_attribute.cdata
337      end
338
339   attlist_id
340      require
341         building_attlist
342      do
343         current_attribute.id
344      end
345
346   attlist_idref
347      require
348         building_attlist
349      do
350         current_attribute.idref
351      end
352
353   attlist_idrefs
354      require
355         building_attlist
356      do
357         current_attribute.idrefs
358      end
359
360   attlist_nmtoken
361      require
362         building_attlist
363      do
364         current_attribute.nmtoken
365      end
366
367   attlist_nmtokens
368      require
369         building_attlist
370      do
371         current_attribute.nmtokens
372      end
373
374   attlist_entity
375      require
376         building_attlist
377      do
378         current_attribute.entity
379      end
380
381   attlist_entities
382      require
383         building_attlist
384      do
385         current_attribute.entities
386      end
387
388   attlist_notation
389      require
390         building_attlist
391      do
392         current_attribute.notation
393      end
394
395   attlist_required
396      require
397         building_attlist
398      do
399         current_attribute.required
400      end
401
402   attlist_implied
403      require
404         building_attlist
405      do
406         current_attribute.implied
407      end
408
409   attlist_valid_fixed (value: UNICODE_STRING): BOOLEAN
410      require
411         building_attlist
412      do
413         Result := current_attribute.valid_fixed_value(value)
414      end
415
416   attlist_fixed (value: UNICODE_STRING)
417      require
418         building_attlist
419         attlist_valid_fixed(value)
420      do
421         current_attribute.fixed(value)
422      end
423
424   attlist_default_value (value: UNICODE_STRING)
425      require
426         building_attlist
427      do
428         current_attribute.default_value(value)
429      end
430
431feature {XML_DTD_VALIDATOR} -- Constructor
432   make (a_name: like name)
433      require
434         not a_name.is_empty
435      do
436         is_built := False
437         structure := Void
438         -- the element's proper attributes:
439         name := a_name
440         if attributes = Void then
441            create attributes.make
442         else
443            attributes.clear_count
444         end
445         current_attribute := Void
446      ensure
447         not is_built
448         structure = Void
449         name = a_name
450         attributes.is_empty
451         current_attribute = Void
452      end
453
454feature {RECYCLING_POOL}
455   recycle
456      do
457         is_built := False
458         structure := Void
459         current_attribute := Void
460         recycle_attributes
461      ensure
462         not is_built
463         structure = Void
464         current_attribute = Void
465      end
466
467feature {} -- Memory management
468   attributes_pool: RECYCLING_POOL[XML_DTD_ATTRIBUTE]
469      once
470         create Result.make
471      end
472
473   recycle_attributes
474      local
475         i: INTEGER
476      do
477         from
478            i := attributes.lower
479         until
480            i > attributes.upper
481         loop
482            attributes_pool.recycle(attributes.item(i))
483            i := i + 1
484         end
485         attributes.clear_count
486      ensure
487         attributes.is_empty
488      end
489
490feature {} -- fill_tagged_out_memory
491   do_fill_tagged_out_memory
492      do
493         tagged_out_memory.extend('<')
494         name.utf8_encode_in(tagged_out_memory)
495         tagged_out_memory.append(once ": ")
496         if structure = Void then
497            tagged_out_memory.append(once "unknown")
498         else
499            structure.fill_tagged_out_memory
500         end
501         tagged_out_memory.extend('>')
502      end
503
504invariant
505   not name.is_empty
506   attributes /= Void
507
508end -- class XML_DTD_ELEMENT
509--
510-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
511--
512-- Permission is hereby granted, free of charge, to any person obtaining a copy
513-- of this software and associated documentation files (the "Software"), to deal
514-- in the Software without restriction, including without limitation the rights
515-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
516-- copies of the Software, and to permit persons to whom the Software is
517-- furnished to do so, subject to the following conditions:
518--
519-- The above copyright notice and this permission notice shall be included in
520-- all copies or substantial portions of the Software.
521--
522-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
523-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
524-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
525-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
526-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
527-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
528-- THE SOFTWARE.