voruby 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. data/Rakefile.rb +107 -224
  2. data/lib/misc.rb +1 -0
  3. data/lib/misc/misc.rb +60 -0
  4. data/lib/misc/propertyfile.rb +31 -0
  5. data/lib/symphony.rb +1 -0
  6. data/lib/symphony/symphony.rb +247 -0
  7. data/lib/voruby.rb +186 -0
  8. data/lib/voruby/active_votable/active_votable.rb +468 -347
  9. data/lib/voruby/adql/1.0/adql.rb +2418 -0
  10. data/lib/voruby/adql/support.rb +2 -0
  11. data/lib/voruby/misc.rb +351 -0
  12. data/lib/voruby/misc/connection_monitor.rb +97 -0
  13. data/lib/voruby/misc/libxml_ext.rb +121 -0
  14. data/lib/voruby/misc/rexml_ext.rb +223 -0
  15. data/lib/voruby/resolver/resolver.rb +12 -0
  16. data/lib/voruby/resolver/sesame.rb +299 -0
  17. data/lib/voruby/sky_query/sky_query.rb +192 -0
  18. data/lib/voruby/stc/1.10/coords.rb +2272 -0
  19. data/lib/voruby/stc/1.10/region.rb +892 -0
  20. data/lib/voruby/stc/1.10/stc.rb +3271 -0
  21. data/lib/voruby/stc/1.30/stc.rb +8666 -0
  22. data/lib/voruby/stc/support.rb +2 -0
  23. data/lib/voruby/ucd/ucd.rb +173 -0
  24. data/lib/voruby/voevent/1.1/voevent.rb +1124 -0
  25. data/lib/voruby/voevent/support.rb +5 -0
  26. data/lib/voruby/votable/1.0/votable.rb +1807 -0
  27. data/lib/voruby/votable/1.1/votable.rb +2100 -0
  28. data/lib/voruby/votable/votable.rb +305 -0
  29. data/lib/voruby/wesix/wesix.rb +491 -0
  30. data/lib/voruby/xlink/1.2/xlink.rb +21 -0
  31. data/test/voruby/active_votable/complex.vot +60 -0
  32. data/test/voruby/active_votable/error.vot +6 -0
  33. data/test/voruby/active_votable/large.vot +130040 -0
  34. data/test/voruby/active_votable/simple1.vot +38 -0
  35. data/test/voruby/active_votable/simple2.vot +38 -0
  36. data/test/voruby/active_votable/test.rb +193 -0
  37. data/test/voruby/adql/1.0/adql-alias.sql +1 -0
  38. data/test/voruby/adql/1.0/adql-alias.xml +26 -0
  39. data/test/voruby/adql/1.0/adql-avg.sql +1 -0
  40. data/test/voruby/adql/1.0/adql-avg.xml +31 -0
  41. data/test/voruby/adql/1.0/adql-circle.sql +1 -0
  42. data/test/voruby/adql/1.0/adql-circle.xml +46 -0
  43. data/test/voruby/adql/1.0/adql-expr.sql +1 -0
  44. data/test/voruby/adql/1.0/adql-expr.xml +34 -0
  45. data/test/voruby/adql/1.0/adql-function.sql +1 -0
  46. data/test/voruby/adql/1.0/adql-function.xml +41 -0
  47. data/test/voruby/adql/1.0/adql-group.sql +1 -0
  48. data/test/voruby/adql/1.0/adql-group.xml +51 -0
  49. data/test/voruby/adql/1.0/adql-having.sql +1 -0
  50. data/test/voruby/adql/1.0/adql-having.xml +25 -0
  51. data/test/voruby/adql/1.0/adql-like.sql +1 -0
  52. data/test/voruby/adql/1.0/adql-like.xml +17 -0
  53. data/test/voruby/adql/1.0/adql-order.sql +1 -0
  54. data/test/voruby/adql/1.0/adql-order.xml +37 -0
  55. data/test/voruby/adql/1.0/adql-simple.sql +1 -0
  56. data/test/voruby/adql/1.0/adql-simple.xml +12 -0
  57. data/test/voruby/adql/1.0/adql-top.sql +1 -0
  58. data/test/voruby/adql/1.0/adql-top.xml +33 -0
  59. data/test/voruby/adql/1.0/test.rb +2220 -0
  60. data/test/voruby/misc/test.rb +32 -0
  61. data/test/voruby/resolver/sesame/test.rb +56 -0
  62. data/test/voruby/sky_query/test.rb +107 -0
  63. data/test/voruby/stc/1.10/coords_test.rb +3704 -0
  64. data/test/voruby/stc/1.10/region_test.rb +993 -0
  65. data/test/voruby/stc/1.10/stc-catalog-entry-location.xml +112 -0
  66. data/test/voruby/stc/1.10/stc-obs-data-location.xml +126 -0
  67. data/test/voruby/stc/1.10/stc-region-circle.xml +5 -0
  68. data/test/voruby/stc/1.10/stc-region-convex.xml +11 -0
  69. data/test/voruby/stc/1.10/stc-region-convexhull.xml +5 -0
  70. data/test/voruby/stc/1.10/stc-region-ellipse.xml +7 -0
  71. data/test/voruby/stc/1.10/stc-region-intersection.xml +25 -0
  72. data/test/voruby/stc/1.10/stc-region-negation.xml +7 -0
  73. data/test/voruby/stc/1.10/stc-region-polygon.xml +13 -0
  74. data/test/voruby/stc/1.10/stc-region-sector.xml +6 -0
  75. data/test/voruby/stc/1.10/stc-region-union.xml +25 -0
  76. data/test/voruby/stc/1.10/stc-resource-profile.xml +60 -0
  77. data/test/voruby/stc/1.10/stc-search-location.xml +54 -0
  78. data/test/voruby/stc/1.10/stc_test.rb +4626 -0
  79. data/test/voruby/stc/1.30/stc-catalog-entry-location.xml +210 -0
  80. data/test/voruby/stc/1.30/stc-obs-data-location-arecibo.xml +353 -0
  81. data/test/voruby/stc/1.30/stc-obs-data-location-fits.xml +250 -0
  82. data/test/voruby/stc/1.30/stc-obs-data-location-xlink.xml +63 -0
  83. data/test/voruby/stc/1.30/stc-obs-data-location.xml +216 -0
  84. data/test/voruby/stc/1.30/stc-resource-profile-unusual-ref-pos.xml +39 -0
  85. data/test/voruby/stc/1.30/stc-resource-profile.xml +129 -0
  86. data/test/voruby/stc/1.30/stc-search-location-arecibo.xml +86 -0
  87. data/test/voruby/stc/1.30/stc-search-location.xml +101 -0
  88. data/test/voruby/stc/1.30/test.rb +6274 -0
  89. data/test/voruby/ucd/test.rb +48 -0
  90. data/test/voruby/voevent/1.1/test.rb +812 -0
  91. data/test/{voevent/voevent_v1_1.xml → voruby/voevent/1.1/voevent.xml} +2 -2
  92. data/test/voruby/voregistry/0.3/test.rb +137 -0
  93. data/test/voruby/votable/1.0/test.rb +714 -0
  94. data/test/voruby/votable/1.0/votable.basic.xml +660 -0
  95. data/test/voruby/votable/1.0/votable.html +86 -0
  96. data/test/voruby/votable/1.0/votable.ns.xml +56 -0
  97. data/test/voruby/votable/1.1/test.rb +785 -0
  98. data/test/voruby/votable/1.1/votable.basic.xml +38 -0
  99. data/test/voruby/votable/1.1/votable.html +86 -0
  100. data/test/voruby/votable/1.1/votable.ns.xml +56 -0
  101. data/test/voruby/votable/test.rb +15 -0
  102. data/test/voruby/wesix/test.rb +268 -0
  103. data/test/voruby/wesix/testr.fits +28 -0
  104. metadata +234 -247
  105. data/REQUIREMENTS +0 -6
  106. data/lib/voruby/active_votable/loader.rb +0 -5
  107. data/lib/voruby/adql/adql.rb +0 -2787
  108. data/lib/voruby/adql/ext.rb +0 -14
  109. data/lib/voruby/adql/loader.rb +0 -6
  110. data/lib/voruby/adql/operations.rb +0 -54
  111. data/lib/voruby/adql/parser.rb +0 -160
  112. data/lib/voruby/adql/transforms.rb +0 -573
  113. data/lib/voruby/ext.rb +0 -17
  114. data/lib/voruby/loader.rb +0 -4
  115. data/lib/voruby/misc/propertyfile.rb +0 -36
  116. data/lib/voruby/plastic/applications.rb +0 -174
  117. data/lib/voruby/plastic/constants.rb +0 -30
  118. data/lib/voruby/plastic/loader.rb +0 -10
  119. data/lib/voruby/plastic/plastic.rb +0 -1
  120. data/lib/voruby/resources/conesearch/conesearch.rb +0 -9
  121. data/lib/voruby/resources/conesearch/conesearch_v0_2.rb +0 -55
  122. data/lib/voruby/resources/conesearch/conesearch_v0_3.rb +0 -50
  123. data/lib/voruby/resources/conesearch/conesearch_v1_0.rb +0 -72
  124. data/lib/voruby/resources/conesearch/loader.rb +0 -4
  125. data/lib/voruby/resources/loader.rb +0 -50
  126. data/lib/voruby/resources/nodes.rb +0 -190
  127. data/lib/voruby/resources/openskynode/loader.rb +0 -4
  128. data/lib/voruby/resources/openskynode/openskynode.rb +0 -9
  129. data/lib/voruby/resources/openskynode/openskynode_v0_1.rb +0 -54
  130. data/lib/voruby/resources/sia/loader.rb +0 -5
  131. data/lib/voruby/resources/sia/sia.rb +0 -9
  132. data/lib/voruby/resources/sia/sia_v0_6.rb +0 -90
  133. data/lib/voruby/resources/sia/sia_v0_7.rb +0 -89
  134. data/lib/voruby/resources/sia/sia_v1_0.rb +0 -122
  135. data/lib/voruby/resources/stsci.rb +0 -59
  136. data/lib/voruby/resources/vodataservice/coverage_v0_2.rb +0 -195
  137. data/lib/voruby/resources/vodataservice/coverage_v0_3.rb +0 -158
  138. data/lib/voruby/resources/vodataservice/loader.rb +0 -5
  139. data/lib/voruby/resources/vodataservice/vodataservice.rb +0 -9
  140. data/lib/voruby/resources/vodataservice/vodataservice_v0_4.rb +0 -189
  141. data/lib/voruby/resources/vodataservice/vodataservice_v0_5.rb +0 -163
  142. data/lib/voruby/resources/vodataservice/vodataservice_v1_0.rb +0 -221
  143. data/lib/voruby/resources/voregistry/loader.rb +0 -4
  144. data/lib/voruby/resources/voregistry/voregistry.rb +0 -9
  145. data/lib/voruby/resources/voregistry/voregistry_v0_2.rb +0 -40
  146. data/lib/voruby/resources/voregistry/voregistry_v0_3.rb +0 -30
  147. data/lib/voruby/resources/voregistry/voregistry_v1_0.rb +0 -86
  148. data/lib/voruby/resources/voresource/loader.rb +0 -17
  149. data/lib/voruby/resources/voresource/voresource.rb +0 -9
  150. data/lib/voruby/resources/voresource/voresource_v0_10.rb +0 -327
  151. data/lib/voruby/resources/voresource/voresource_v0_9.rb +0 -405
  152. data/lib/voruby/resources/voresource/voresource_v1_0.rb +0 -230
  153. data/lib/voruby/services/ext.rb +0 -11
  154. data/lib/voruby/services/gestalt/footprint.rb +0 -95
  155. data/lib/voruby/services/gestalt/wcs_fixer.rb +0 -105
  156. data/lib/voruby/services/gestalt/wesix.rb +0 -155
  157. data/lib/voruby/services/loader.rb +0 -7
  158. data/lib/voruby/services/registry/registry.rb +0 -53
  159. data/lib/voruby/services/resolver/resolver.rb +0 -35
  160. data/lib/voruby/services/schema/schema.rb +0 -644
  161. data/lib/voruby/sesame/loader.rb +0 -6
  162. data/lib/voruby/sesame/sesame_v1_0.rb +0 -64
  163. data/lib/voruby/simple/loader.rb +0 -6
  164. data/lib/voruby/simple/parameters.rb +0 -196
  165. data/lib/voruby/simple/sap.rb +0 -446
  166. data/lib/voruby/spacetime/loader.rb +0 -3
  167. data/lib/voruby/spacetime/spacetime.rb +0 -607
  168. data/lib/voruby/stc/coords_v1_20.rb +0 -900
  169. data/lib/voruby/stc/loader.rb +0 -55
  170. data/lib/voruby/stc/region_v1_20.rb +0 -274
  171. data/lib/voruby/stc/stc_v1_20.rb +0 -1196
  172. data/lib/voruby/util.rb +0 -27
  173. data/lib/voruby/voevent/loader.rb +0 -7
  174. data/lib/voruby/voevent/voevent_v1_0.rb +0 -213
  175. data/lib/voruby/voevent/voevent_v1_1.rb +0 -196
  176. data/lib/voruby/votables/chandra.rb +0 -373
  177. data/lib/voruby/votables/data.rb +0 -179
  178. data/lib/voruby/votables/galex.rb +0 -377
  179. data/lib/voruby/votables/int.rb +0 -354
  180. data/lib/voruby/votables/libxml_parser.rb +0 -411
  181. data/lib/voruby/votables/libxml_votable.rb +0 -67
  182. data/lib/voruby/votables/loader.rb +0 -10
  183. data/lib/voruby/votables/meta.rb +0 -763
  184. data/lib/voruby/votables/misc.rb +0 -51
  185. data/lib/voruby/votables/nsa.rb +0 -410
  186. data/lib/voruby/votables/rexml_parser.rb +0 -408
  187. data/lib/voruby/votables/rexml_votable.rb +0 -67
  188. data/lib/voruby/votables/sdss.rb +0 -356
  189. data/lib/voruby/votables/transforms.rb +0 -388
  190. data/lib/voruby/votables/tree.rb +0 -45
  191. data/lib/voruby/votables/types.rb +0 -391
  192. data/lib/voruby/votables/votable.rb +0 -687
  193. data/test/active_votable/database.yml +0 -6
  194. data/test/active_votable/test.vot +0 -168492
  195. data/test/active_votable/unittest.rb +0 -41
  196. data/test/adql/test1.adql +0 -49
  197. data/test/adql/test2.adql +0 -51
  198. data/test/adql/test3.adql +0 -81
  199. data/test/adql/test4.adql +0 -53
  200. data/test/adql/test5.adql +0 -55
  201. data/test/adql/test6.adql +0 -18
  202. data/test/adql/test7.adql +0 -48
  203. data/test/adql/unittest.rb +0 -1672
  204. data/test/plastic/test.rb +0 -44
  205. data/test/plastic/test.vot +0 -5385
  206. data/test/plastic/unittest.rb +0 -66
  207. data/test/resources/conesearch/conesearch_v0_3.xml +0 -31
  208. data/test/resources/conesearch/conesearch_v1_0.xml +0 -86
  209. data/test/resources/conesearch/unittest_v0_3.rb +0 -22
  210. data/test/resources/conesearch/unittest_v1_0.rb +0 -24
  211. data/test/resources/openskynode/open_sky_node_v0_1.xml +0 -32
  212. data/test/resources/openskynode/unittest_v0_1.rb +0 -31
  213. data/test/resources/sia/simple_image_access_v0_7.xml +0 -36
  214. data/test/resources/sia/simple_image_access_v1_0.xml +0 -122
  215. data/test/resources/sia/unittest_v0_7.rb +0 -24
  216. data/test/resources/sia/unittest_v1_0.rb +0 -29
  217. data/test/resources/stsci.xml +0 -336
  218. data/test/resources/unittest_stsci.rb +0 -25
  219. data/test/resources/vodataservice/catalog_service_resource_v1_0.xml +0 -128
  220. data/test/resources/vodataservice/data_collection_resource_v0_5.xml +0 -54
  221. data/test/resources/vodataservice/data_collection_resource_v1_0.xml +0 -117
  222. data/test/resources/vodataservice/data_service_resource_v1_0.xml +0 -115
  223. data/test/resources/vodataservice/sky_service_resource_v0_10.xml +0 -45
  224. data/test/resources/vodataservice/table_service_resource_v1_0.xml +0 -122
  225. data/test/resources/vodataservice/tabular_sky_service_resource_v0_10.xml +0 -60
  226. data/test/resources/vodataservice/unittest_v0_5.rb +0 -126
  227. data/test/resources/vodataservice/unittest_v1_0.rb +0 -151
  228. data/test/resources/voregistry/authority_resource_v0_3.xml +0 -20
  229. data/test/resources/voregistry/authority_resource_v1_0.xml +0 -82
  230. data/test/resources/voregistry/registry_service_v0_3.xml +0 -20
  231. data/test/resources/voregistry/registry_service_v1_0.xml +0 -107
  232. data/test/resources/voregistry/unittest_v0_3.rb +0 -31
  233. data/test/resources/voregistry/unittest_v1_0.rb +0 -34
  234. data/test/resources/voresource/organisation_resource_v1_0.xml +0 -90
  235. data/test/resources/voresource/resource_organisation_v0_10.xml +0 -22
  236. data/test/resources/voresource/resource_service_v0_10.xml +0 -19
  237. data/test/resources/voresource/resource_v0_10.xml +0 -19
  238. data/test/resources/voresource/resource_v1_0.xml +0 -79
  239. data/test/resources/voresource/service_resource_v1_0.xml +0 -91
  240. data/test/resources/voresource/unittest_v0_10.rb +0 -61
  241. data/test/resources/voresource/unittest_v0_9.rb +0 -4
  242. data/test/resources/voresource/unittest_v1_0.rb +0 -190
  243. data/test/services/gestalt/unittest.rb +0 -74
  244. data/test/services/registry/unittest.rb +0 -34
  245. data/test/services/resolver/unittest.rb +0 -38
  246. data/test/simple/unittest.rb +0 -46
  247. data/test/spacetime/unittest.rb +0 -39
  248. data/test/stc/catalog_entry_location_v1_20.xml +0 -112
  249. data/test/stc/obs_data_location_v1_20.xml +0 -108
  250. data/test/stc/search_location_v1_20.xml +0 -54
  251. data/test/stc/stc_resource_profile_v1_20.xml +0 -60
  252. data/test/stc/unittest_v1_20.rb +0 -620
  253. data/test/voevent/unittest_v1_0.rb +0 -79
  254. data/test/voevent/unittest_v1_1.rb +0 -70
  255. data/test/voevent/voevent_v1_0.xml +0 -96
  256. data/test/votables/test.vot +0 -366
  257. data/test/votables/unittest.rb +0 -54
@@ -0,0 +1,892 @@
1
+ require 'voruby/stc/support'
2
+ require 'voruby/stc/1.10/coords'
3
+ include VORuby::STC::V1_10::Coords
4
+
5
+ module VORuby
6
+ module STC
7
+ module V1_10
8
+ module Region
9
+ include XMLUtilities
10
+
11
+ # Region is the base type for everything.
12
+ class RegionType
13
+ include SerializableToXml
14
+
15
+ attr_reader :note
16
+
17
+ def initialize(options={})
18
+ options.each { |key, value| send("#{key}=", value) }
19
+ end
20
+
21
+ # The fill_factor (value between 0 and 1) indicates the fraction of the region that
22
+ # is actually included; possible application: large scale resource coverage areas
23
+ def fill_factor
24
+ @fill_factor || 1.0
25
+ end
26
+
27
+ def fill_factor=(f)
28
+ raise ArgumentError, "fill factor must be between 0.0 and 1.0" if f and (Float(f) < 0.0 or Float(f) > 1.0)
29
+ @fill_factor = f ? Float(f) : nil
30
+ end
31
+
32
+ def note=(n)
33
+ @note = n ? n.to_s : nil
34
+ end
35
+
36
+ def ==(r)
37
+ self.fill_factor == r.fill_factor and
38
+ self.note == r.note
39
+ end
40
+
41
+ def to_xml(name=nil)
42
+ el = element(name)
43
+
44
+ el.attributes["#{obj_ns.prefix}:fill_factor"] = self.fill_factor.to_s if self.fill_factor
45
+ el.attributes["#{obj_ns.prefix}:note"] = self.note if self.note
46
+
47
+ collapse_namespaces(el)
48
+ el
49
+ end
50
+
51
+ def self.from_xml(xml)
52
+ root = element_from(xml)
53
+
54
+ options = {}
55
+
56
+ fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
57
+ options[:fill_factor] = Float(fill_factor.value) if fill_factor
58
+
59
+ note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
60
+ options[:note] = note.value if note
61
+
62
+ self.new(options)
63
+ end
64
+ end
65
+
66
+ module Region; end
67
+
68
+ # Shape is the abstract type that is the building block of regions; in real life it needs to be replaced by a concrete shape
69
+ class Shape < RegionType
70
+ include SerializableToXml
71
+
72
+ attr_reader :coord_system_id, :unit
73
+
74
+ def initialize(options={})
75
+ raise_argument_required_error('coord system id') if !options.has_key?(:coord_system_id)
76
+ options.each { |key, value| send("#{key}=", value) }
77
+ end
78
+
79
+ def coord_system_id=(id)
80
+ raise_argument_required_error('coord sys id') if !id
81
+ @coord_system_id = id.is_a?(IdRef) ? id : IdRef.new(id.to_s)
82
+ end
83
+
84
+ def unit=(u)
85
+ # unit should be required according to the schema, but I've seen
86
+ # examples (even in the official docs) where it's not.
87
+ if u
88
+ @unit = u.is_a?(PosUnit) ? u : PosUnit.new(u.to_s)
89
+ else
90
+ nil
91
+ end
92
+ end
93
+
94
+ def ==(s)
95
+ self.coord_system_id == s.coord_system_id and
96
+ self.unit == s.unit
97
+ end
98
+
99
+ def to_xml(name=nil)
100
+ el = super(name)
101
+
102
+ el.attributes["#{obj_ns.prefix}:coord_system_id"] = self.coord_system_id.to_s
103
+ el.attributes["#{obj_ns.prefix}:unit"] = self.unit.to_s if self.unit
104
+
105
+ collapse_namespaces(el)
106
+
107
+ el
108
+ end
109
+ end
110
+
111
+ # Circle shape: center and radius
112
+ class CircleType < Shape
113
+ attr_reader :center, :radius
114
+
115
+ def self.xml_type; 'circleType' end
116
+
117
+ def initialize(options={})
118
+ raise_argument_required_error('center') if !options.has_key?(:center)
119
+ raise_argument_required_error('radius') if !options.has_key?(:radius)
120
+ super(options)
121
+ end
122
+
123
+ # The coordinates of the circle's center
124
+ def center=(c)
125
+ raise_argument_required_error('center') if !c
126
+ @center = Double2.new(c)
127
+ end
128
+
129
+ # The radius of the circle
130
+ def radius=(r)
131
+ raise_argument_required_error('radius') if !r
132
+ @radius = Float(r)
133
+ end
134
+
135
+ def ==(s)
136
+ super(s) and
137
+ self.center == s.center and
138
+ self.radius == s.radius
139
+ end
140
+
141
+ def to_xml(name=nil)
142
+ el = super(name)
143
+
144
+ el.add_element(self.center.to_xml("Center", obj_ns))
145
+ radius = REXML::Element.new("#{obj_ns.prefix}:Radius")
146
+ radius.text = self.radius.to_s
147
+ el.add_element(radius)
148
+
149
+ collapse_namespaces(el)
150
+ el
151
+ end
152
+
153
+ def to_s
154
+ "CIRCLE #{self.coord_system_id} #{self.center} #{self.radius}"
155
+ end
156
+
157
+ def self.from_xml(xml)
158
+ root = element_from(xml)
159
+
160
+ fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
161
+ note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
162
+ unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
163
+ options = {
164
+ :fill_factor => fill_factor ? Float(fill_factor.value) : nil,
165
+ :note => note ? note.value : nil,
166
+ :coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
167
+ :unit => unit ? PosUnit.new(unit.value) : nil,
168
+ :center => Double2.from_xml(REXML::XPath.first(root, 'x:Center', {'x' => obj_ns.uri})),
169
+ :radius => Float(REXML::XPath.first(root, 'x:Radius', {'x' => obj_ns.uri}).text)
170
+ }
171
+
172
+ self.new(options)
173
+ end
174
+ end
175
+
176
+ class Circle < CircleType
177
+ include Region
178
+ end
179
+
180
+ # AllSky is just a convenience, meaning no bounds
181
+ class AllSky < RegionType
182
+ include Region
183
+
184
+ def to_xml(name=nil)
185
+ el = super(name)
186
+ el
187
+ end
188
+
189
+ def to_s
190
+ "ALLSKY"
191
+ end
192
+ end
193
+
194
+ # Ellipse shape: adds semi-minor axis and position angle to Circle
195
+ class EllipseType < CircleType
196
+ attr_reader :minor_radius, :pos_angle
197
+
198
+ def self.xml_type; 'ellipseType' end
199
+
200
+ def initialize(options={})
201
+ raise_argument_required_error('minor radius') if !options.has_key?(:minor_radius)
202
+ raise_argument_required_error('position angle') if !options.has_key?(:pos_angle)
203
+ super(options)
204
+ end
205
+
206
+ # Half the minor axis of the ellipse, in radius_unit
207
+ def minor_radius=(r)
208
+ raise_argument_required_error('minor radius') if !r
209
+ @minor_radius = Float(r)
210
+ end
211
+
212
+ # Position angle of major axis (Radius), counter-clockwise from north in pos_angle_unit
213
+ def pos_angle=(a)
214
+ raise_argument_required_error('position angle') if !a
215
+ @pos_angle = Float(a)
216
+ end
217
+
218
+ def pos_angle_unit=(u)
219
+ raise ArgumentError, 'position angle unit required' if !u
220
+ @pos_angle_unit = u.is_a?(AngleUnit) ? u : AngleUnit.new(u.to_s)
221
+ end
222
+
223
+ def pos_angle_unit
224
+ @pos_angle_unit || AngleUnit.new('deg')
225
+ end
226
+
227
+ def ==(s)
228
+ super(s) and
229
+ self.minor_radius = s.minor_radius and
230
+ self.pos_angle = s.pos_angle and
231
+ self.pos_angle_unit = s.pos_angle_unit
232
+ end
233
+
234
+ def to_xml(name=nil)
235
+ el = super(name)
236
+
237
+ el.attributes["#{obj_ns.prefix}:pos_angle_unit"] = self.pos_angle_unit.to_s
238
+
239
+ minor_radius = REXML::Element.new("#{obj_ns.prefix}:MinorRadius")
240
+ minor_radius.text = self.minor_radius.to_s
241
+ el.add_element(minor_radius)
242
+
243
+ pos_angle = REXML::Element.new("#{obj_ns.prefix}:PosAngle")
244
+ pos_angle.text = self.pos_angle.to_s
245
+ el.add_element(pos_angle)
246
+
247
+ collapse_namespaces(el)
248
+
249
+ el
250
+ end
251
+
252
+ def to_s
253
+ "ELLIPSE #{self.coord_system_id} #{self.center} #{self.radius} #{self.minor_radius} #{self.pos_angle}"
254
+ end
255
+
256
+ def self.from_xml(xml)
257
+ root = element_from(xml)
258
+
259
+ fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
260
+ note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
261
+ unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
262
+ options = {
263
+ :fill_factor => fill_factor ? Float(fill_factor.value) : nil,
264
+ :note => note ? note.value : nil,
265
+ :coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
266
+ :pos_angle_unit => AngleUnit.new(root.attributes.get_attribute_ns(obj_ns.uri, 'pos_angle_unit').value),
267
+ :unit => unit ? PosUnit.new(unit.value) : nil,
268
+ :center => Double2.from_xml(REXML::XPath.first(root, 'x:Center', {'x' => obj_ns.uri})),
269
+ :radius => Float(REXML::XPath.first(root, 'x:Radius', {'x' => obj_ns.uri}).text),
270
+ :minor_radius => Float(REXML::XPath.first(root, 'x:MinorRadius', {'x' => obj_ns.uri}).text),
271
+ :pos_angle => Float(REXML::XPath.first(root, 'x:PosAngle', {'x' => obj_ns.uri}).text)
272
+ }
273
+
274
+ self.new(options)
275
+ end
276
+ end
277
+
278
+ class Ellipse < EllipseType
279
+ include Region
280
+ end
281
+
282
+ # SmallCircle is used in vertices to indicate that the polygon side associated with the vertex
283
+ # is to be a small circle rather than the default great circle.
284
+ # SmallCircle indicates in polygons that side is along small circle; with optional pole.
285
+ class SmallCircle
286
+ include SerializableToXml
287
+
288
+ attr_reader :pole
289
+
290
+ def initialize(options={})
291
+ options.is_a?(Hash) ? options.each { |key, value| send("#{key}=", value) } : self.pole = options
292
+ end
293
+
294
+ def pole=(p)
295
+ p = Double2.new(p) if p and p.class == Array
296
+ raise_type_mismatch_error(p, Double2) if p
297
+ @pole = p
298
+ end
299
+
300
+ def ==(c)
301
+ self.pole == c.pole
302
+ end
303
+
304
+ def to_xml(name=nil)
305
+ el = element(name)
306
+
307
+ el.add_element(self.pole.to_xml('Pole', obj_ns)) if pole
308
+
309
+ collapse_namespaces(el)
310
+
311
+ el
312
+ end
313
+
314
+ def self.from_xml(xml)
315
+ root = element_from(xml)
316
+
317
+ options = {}
318
+ pole = REXML::XPath.first(root, 'x:Pole', {'x' => obj_ns.uri})
319
+ options[:pole] = Double2.from_xml(pole) if pole
320
+
321
+ SmallCircle.new(options)
322
+ end
323
+ end
324
+
325
+ # Vertex is a position with optional SmallCircle element
326
+ class Vertex
327
+ include SerializableToXml
328
+
329
+ attr_reader :position, :small_circle
330
+
331
+ def initialize(options={})
332
+ raise_argument_required_error('position') if !options.has_key?(:position)
333
+ options.each { |key, value| send("#{key}=", value) }
334
+ end
335
+
336
+ def position=(p)
337
+ raise_argument_required_error('position') if !p
338
+ p = Double2.new(p) if p.class == Array
339
+ raise_type_mismatch_error(p, Double2)
340
+ @position = p
341
+ end
342
+
343
+ def small_circle=(c)
344
+ raise_type_mismatch_error(c, SmallCircle) if c
345
+ @small_circle = c
346
+ end
347
+
348
+ def ==(v)
349
+ self.position == v.position and
350
+ self.small_circle == v.small_circle
351
+ end
352
+
353
+ def to_xml(name=nil)
354
+ el = element(name)
355
+
356
+ el.add_element(self.position.to_xml('Position', obj_ns))
357
+ el.add_element(self.small_circle.to_xml('SmallCircle')) if self.small_circle
358
+
359
+ collapse_namespaces(el)
360
+
361
+ el
362
+ end
363
+
364
+ def to_s
365
+ self.position.to_s
366
+ end
367
+
368
+ def self.from_xml(xml)
369
+ root = element_from(xml)
370
+
371
+ options = {
372
+ :position => Double2.from_xml(REXML::XPath.first(root, 'x:Position', {'x' => obj_ns.uri}))
373
+ }
374
+
375
+ small_circle = REXML::XPath.first(root, 'x:SmallCircle', {'x' => obj_ns.uri})
376
+ options[:small_circle] = SmallCircle.from_xml(small_circle) if small_circle
377
+
378
+ Vertex.new(options)
379
+ end
380
+ end
381
+
382
+ class VertexList < TypedArray
383
+ def self.restricted_to; [Vertex] end
384
+ def self.minimum_length; 1 end
385
+ end
386
+
387
+ # Polygon: one or more vertices; counter-clockwise encircled area is enclosed;
388
+ # cyclical coordinates may exceed 0 and 360 limits if necessary
389
+ class PolygonType < Shape
390
+ attr_reader :vertices
391
+
392
+ def self.xml_type; 'polygonType' end
393
+
394
+ def initialize(options={})
395
+ raise_argument_required_error('list of vertexes') if !options.has_key?(:vertices)
396
+ super(options)
397
+ end
398
+
399
+ # In order to form polygons, vertices are to be connected with straight line segments.
400
+ # In the case of spherical coordinates: GreatCircle segments; if a SmallCircle element
401
+ # is present, the vertex and its predecessor are to be connected with a SmallCircle, by
402
+ # default in the CoordSys that is referenced; optionally, a pole may be specified (other
403
+ # than the CoordSys pole) that defines the SmallCircle system
404
+ def vertices=(vs)
405
+ raise_argument_required_error('list of vertexes') if !vs
406
+
407
+ vs = VertexList.new(vs) if vs.class == Array
408
+ raise_type_mismatch_error(vs, VertexList)
409
+
410
+ @vertices = vs
411
+ end
412
+
413
+ def ==(p)
414
+ super(p) and
415
+ self.vertices == p.vertices
416
+ end
417
+
418
+ def to_xml(name=nil)
419
+ el = super(name)
420
+ self.vertices.each { |v| el.add_element(v.to_xml('Vertex')) }
421
+ collapse_namespaces(el)
422
+ el
423
+ end
424
+
425
+ def to_s
426
+ "POLYGON #{self.coord_system_id} #{self.vertices.collect{ |v| v.to_s }.join(' ')}"
427
+ end
428
+
429
+ def self.from_xml(xml)
430
+ root = element_from(xml)
431
+
432
+ fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
433
+ note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
434
+ unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
435
+ options = {
436
+ :fill_factor => fill_factor ? Float(fill_factor.value) : nil,
437
+ :note => note ? note.value : nil,
438
+ :coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
439
+ :unit => unit ? PosUnit.new(unit.value) : nil,
440
+ :vertices => VertexList.new(xml_to_obj(root, Vertex))
441
+ }
442
+
443
+ self.new(options)
444
+ end
445
+ end
446
+
447
+ class Polygon < PolygonType
448
+ include Region
449
+ end
450
+
451
+ # A sector is the counter-clockwise area between two half-lines
452
+ class SectorType < Shape
453
+ attr_reader :position, :pos_angle1, :pos_angle2
454
+
455
+ def self.xml_type; 'sectorType' end
456
+
457
+ def initialize(options)
458
+ raise_argument_required_error('position') if !options.has_key?(:position)
459
+ raise_argument_required_error('position angle 1') if !options.has_key?(:pos_angle1)
460
+ raise_argument_required_error('position angle 2') if !options.has_key?(:pos_angle2)
461
+ super(options)
462
+ end
463
+
464
+ # The vertex position of the sector
465
+ def position=(p)
466
+ raise_argument_required_error('position') if !p
467
+ p = Double2.new(p) if p.class == Array
468
+ raise_type_mismatch_error(p, Double2)
469
+ @position = p
470
+ end
471
+
472
+ # The area ccw from this position angle is included
473
+ def pos_angle1=(a)
474
+ raise_argument_required_error('position angle 1') if !a
475
+ @pos_angle1 = Float(a)
476
+ end
477
+
478
+ # The area cw from this position angle is included
479
+ def pos_angle2=(a)
480
+ raise_argument_required_error('position angle 2') if !a
481
+ @pos_angle2 = Float(a)
482
+ end
483
+
484
+ def pos_angle_unit=(u)
485
+ raise_argument_required_error('position angle unit') if !u
486
+ @pos_angle_unit = u.is_a?(PosUnit) ? u : PosUnit.new(u.to_s)
487
+ end
488
+
489
+ def pos_angle_unit
490
+ @pos_angle_unit || PosUnit.new('deg')
491
+ end
492
+
493
+ def ==(s)
494
+ super(s) and
495
+ self.position == s.position and
496
+ self.pos_angle1 == s.pos_angle1 and
497
+ self.pos_angle2 == s.pos_angle2 and
498
+ self.pos_angle_unit == s.pos_angle_unit
499
+ end
500
+
501
+ def to_xml(name=nil)
502
+ el = super(name)
503
+
504
+ el.attributes["#{obj_ns.prefix}:pos_angle_unit"] = self.pos_angle_unit.to_s
505
+
506
+ el.add_element(self.position.to_xml('Position', obj_ns))
507
+
508
+ pos_angle1 = REXML::Element.new("#{obj_ns.prefix}:PosAngle1")
509
+ pos_angle1.text = self.pos_angle1.to_s
510
+ el.add_element(pos_angle1)
511
+
512
+ pos_angle2 = REXML::Element.new("#{obj_ns.prefix}:PosAngle2")
513
+ pos_angle2.text = self.pos_angle2.to_s
514
+ el.add_element(pos_angle2)
515
+
516
+ collapse_namespaces(el)
517
+
518
+ el
519
+ end
520
+
521
+ def to_s
522
+ "SECTOR #{self.coord_system_id} #{self.position} #{self.pos_angle1} #{self.pos_angle2}"
523
+ end
524
+
525
+ def self.from_xml(xml)
526
+ root = element_from(xml)
527
+
528
+ fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
529
+ note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
530
+ options = {
531
+ :fill_factor => fill_factor ? Float(fill_factor.value) : nil,
532
+ :note => note ? note.value : nil,
533
+ :coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
534
+ :position => Double2.from_xml(REXML::XPath.first(root, 'x:Position', {'x' => obj_ns.uri})),
535
+ :pos_angle1 => Float(REXML::XPath.first(root, 'x:PosAngle1', {'x' => obj_ns.uri}).text),
536
+ :pos_angle2 => Float(REXML::XPath.first(root, 'x:PosAngle2', {'x' => obj_ns.uri}).text)
537
+ }
538
+
539
+ unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
540
+ options[:unit] = PosUnit.new(unit.value) if unit
541
+
542
+ pos_angle_unit = root.attributes.get_attribute_ns(obj_ns.uri, 'pos_angle_unit')
543
+ options[:pos_angle_unit] = PosUnit.new(pos_angle_unit.value) if pos_angle_unit
544
+
545
+ self.new(options)
546
+ end
547
+ end
548
+
549
+ class Sector < SectorType
550
+ include Region
551
+ end
552
+
553
+ # An area on the unit sphere defined by the intersection with a plane
554
+ class Constraint
555
+ include SerializableToXml
556
+
557
+ attr_reader :vector, :offset
558
+
559
+ def initialize(options={})
560
+ raise_argument_required_error('vector') if !options.has_key?(:vector)
561
+ raise_argument_required_error('offset') if !options.has_key?(:offset)
562
+ options.each { |key, value| send("#{key}=", value) }
563
+ end
564
+
565
+ # This needs to be a spherical coordinate vector; it is the unit vector that
566
+ # is normal to the plane that forms a constraint for a convex
567
+ def vector=(v)
568
+ raise_argument_required_error('vector') if !v
569
+ v = Double3.new(v) if v.class == Array
570
+
571
+ raise_type_mismatch_error(v, Double3)
572
+ @vector = v
573
+ end
574
+
575
+ # The distance along the normal vector where the constraint plane intersects
576
+ # that vector; if positive, the spherical sector on the far side (seen from
577
+ # the center) is selected; if negative, the point of intersection is in the
578
+ # opposite direction of the vector, resulting in more than a hemisphere
579
+ def offset=(o)
580
+ raise_argument_required_error('offset') if !o
581
+ @offset = Float(o)
582
+ end
583
+
584
+ def ==(c)
585
+ self.vector == c.vector and
586
+ self.offset == c.offset
587
+ end
588
+
589
+ def to_xml(name=nil)
590
+ el = element(name)
591
+
592
+ el.add_element(self.vector.to_xml('Vector', obj_ns))
593
+
594
+ offset = REXML::Element.new("#{obj_ns.prefix}:Offset")
595
+ offset.text = self.offset.to_s
596
+ el.add_element(offset)
597
+
598
+ collapse_namespaces(el)
599
+
600
+ el
601
+ end
602
+
603
+ def to_s
604
+ "#{self.vector} #{self.offset}"
605
+ end
606
+
607
+ def self.from_xml(xml)
608
+ root = element_from(xml)
609
+
610
+ options = {
611
+ :vector => Double3.from_xml(REXML::XPath.first(root, 'x:Vector', {'x' => obj_ns.uri})),
612
+ :offset => Float(REXML::XPath.first(root, 'x:Offset', {'x' => obj_ns.uri}).text)
613
+ }
614
+
615
+ Constraint.new(options)
616
+ end
617
+ end
618
+
619
+ class ConstraintList < TypedArray
620
+ def self.restricted_to; [Constraint] end
621
+ def self.minimum_length; 1 end
622
+ end
623
+
624
+ # A convex polygon defined by one or more Constraints
625
+ class ConvexType < Shape
626
+ attr_reader :constraints
627
+
628
+ def self.xml_type; 'convexType' end
629
+
630
+ def initialize(options={})
631
+ raise_argument_required_error('list of constraints') if !options.has_key?(:constraints)
632
+ super(options)
633
+ end
634
+
635
+ def constraints=(cs)
636
+ raise_argument_required_error('list of constraints') if !cs
637
+
638
+ cs = ConstraintList.new(cs) if cs.class == Array
639
+ raise_type_mismatch_error(cs, ConstraintList)
640
+
641
+ @constraints = cs
642
+ end
643
+
644
+ def ==(c)
645
+ super(c) and
646
+ self.constraints == c.constraints
647
+ end
648
+
649
+ def to_xml(name=nil)
650
+ el = super(name)
651
+ self.constraints.each { |c| el.add_element(c.to_xml('Constraint')) }
652
+ collapse_namespaces(el)
653
+ el
654
+ end
655
+
656
+ def to_s
657
+ "CONVEX #{self.coord_system_id} #{self.constraints.collect{ |c| c.to_s }.join(' ') }"
658
+ end
659
+
660
+ def self.from_xml(xml)
661
+ root = element_from(xml)
662
+
663
+ fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
664
+ note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
665
+ options = {
666
+ :fill_factor => fill_factor ? Float(fill_factor.value) : nil,
667
+ :note => note ? note.value : nil,
668
+ :coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
669
+ :constraints => REXML::XPath.match(root, 'x:Constraint', {'x' => obj_ns.uri}).collect{ |c| Constraint.from_xml(c) }
670
+ }
671
+ unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
672
+ options[:unit] = PosUnit.new(unit.value) if unit
673
+
674
+ self.new(options)
675
+ end
676
+ end
677
+
678
+ class Convex < ConvexType
679
+ include Region
680
+ end
681
+
682
+ class PointList < TypedArray
683
+ def self.restricted_to; [Double3] end
684
+ def self.minimum_length; 1 end
685
+ end
686
+
687
+ # A convex hull
688
+ class ConvexHullType < Shape
689
+ attr_reader :points
690
+
691
+ def self.xml_type; 'convexHullType' end
692
+
693
+ def initialize(options={})
694
+ raise_argument_required_error('list of points') if !options.has_key?(:points)
695
+ super(options)
696
+ end
697
+
698
+ def points=(ps)
699
+ raise_argument_required_error('list of points') if !ps
700
+
701
+ ps = PointList.new(ps) if ps.class == Array
702
+ raise_type_mismatch_error(ps, PointList)
703
+
704
+ @points = ps
705
+ end
706
+
707
+ def ==(c)
708
+ super(c) and
709
+ self.points == c.points
710
+ end
711
+
712
+ def to_xml(name=nil)
713
+ el = super(name)
714
+ self.points.each { |p| el.add_element(p.to_xml('Point', obj_ns)) }
715
+ collapse_namespaces(el)
716
+ el
717
+ end
718
+
719
+ def to_s
720
+ "CHULL #{self.coord_system_id} #{self.points}"
721
+ end
722
+
723
+ def self.from_xml(xml)
724
+ root = element_from(xml)
725
+
726
+ fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
727
+ note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
728
+ options = {
729
+ :fill_factor => fill_factor ? Float(fill_factor.value) : nil,
730
+ :note => note ? note.value : nil,
731
+ :coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
732
+ :points => PointList.new(
733
+ REXML::XPath.match(root, 'x:Point', {'x' => obj_ns.uri}).collect{ |p| Double3.from_xml(p) }
734
+ )
735
+ }
736
+ unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
737
+ options[:unit] = PosUnit.new(unit.value) if unit
738
+
739
+ self.new(options)
740
+ end
741
+ end
742
+
743
+ class ConvexHull < ConvexHullType
744
+ include Region
745
+ end
746
+
747
+ # This is a generic hook for regions defined in sky indexing schemes
748
+ class SkyIndexType < Shape
749
+ def self.xml_type; 'skyIndexType' end
750
+ end
751
+
752
+ class SkyIndex < SkyIndexType
753
+ include Region
754
+ end
755
+
756
+ class RegionList < TypedArray
757
+ def self.restricted_to; [Region] end
758
+ def self.minimum_length; 2 end
759
+ end
760
+
761
+ class BooleanOperatorType < RegionType
762
+ include SerializableToXml
763
+
764
+ attr_reader :regions
765
+
766
+ def initialize(options={})
767
+ raise_argument_required_error('list of regions') if !options.has_key?(:regions)
768
+ super(options)
769
+ end
770
+
771
+ def regions=(rs)
772
+ raise_argument_required_error('list of regions') if !rs
773
+
774
+ rs = RegionList.new(rs) if rs.class == Array
775
+ raise_type_mismatch_error(rs, RegionList)
776
+
777
+ @regions = rs
778
+ end
779
+
780
+ def ==(u)
781
+ super(u) and
782
+ self.regions == u.regions
783
+ end
784
+
785
+ def to_xml(name=nil)
786
+ el = super(name)
787
+ self.regions.each { |r| el.add_element(r.to_xml) }
788
+ collapse_namespaces(el)
789
+ el
790
+ end
791
+
792
+ def to_s(name)
793
+ "#{name}(#{self.regions.collect{ |r| r.to_s }.join(' ')})"
794
+ end
795
+
796
+ def self.from_xml(xml)
797
+ root = element_from(xml)
798
+
799
+ options = {
800
+ :regions => xml_to_obj(root, Region)
801
+ }
802
+ fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
803
+ options[:fill_factor] = Float(fill_factor.value) if fill_factor
804
+ note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
805
+ options[:note] = note.value if note
806
+
807
+ self.new(options)
808
+ end
809
+ end
810
+
811
+ # The union of two or more regions is a region
812
+ class UnionType < BooleanOperatorType
813
+ def self.xml_type; 'unionType' end
814
+
815
+ def to_s
816
+ super('UNION')
817
+ end
818
+ end
819
+
820
+ class Union < UnionType
821
+ include Region
822
+ end
823
+
824
+ # The intersection of two or more regions is a region
825
+ class IntersectionType < BooleanOperatorType
826
+ def self.xml_type; 'intersectionType' end
827
+
828
+ def to_s
829
+ super('INTERSECT')
830
+ end
831
+ end
832
+
833
+ class Intersection < IntersectionType
834
+ include Region
835
+ end
836
+
837
+ class NegationType < RegionType
838
+ attr_reader :region
839
+
840
+ def self.xml_type; 'negationType' end
841
+
842
+ def initialize(options={})
843
+ raise_argument_required_error('region') if !options.has_key?(:region)
844
+ super(options)
845
+ end
846
+
847
+ def region=(r)
848
+ raise_argument_required_error('region') if !r
849
+ raise TypeError, "invalid value #{r}, expected Region" if !r.is_a?(Region)
850
+
851
+ @region = r
852
+ end
853
+
854
+ def ==(n)
855
+ super(n) and
856
+ self.region == n.region
857
+ end
858
+
859
+ def to_xml(name=nil)
860
+ el = element(name)
861
+ el.add_element(self.region.to_xml)
862
+ collapse_namespaces(name)
863
+ el
864
+ end
865
+
866
+ def to_s
867
+ "NOT(#{self.region})"
868
+ end
869
+
870
+ def self.from_xml(xml)
871
+ root = element_from(xml)
872
+
873
+ options = {
874
+ :region => xml_to_obj(root, Region, true)
875
+ }
876
+ fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
877
+ options[:fill_factor] = Float(fill_factor.value) if fill_factor
878
+ note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
879
+ options[:note] = note.value if note
880
+
881
+ self.new(options)
882
+ end
883
+ end
884
+
885
+ class Negation < NegationType
886
+ include Region
887
+ end
888
+
889
+ end
890
+ end
891
+ end
892
+ end