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