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,2100 @@
1
+ require 'voruby/votable/votable'
2
+
3
+ module VORuby
4
+ module VOTable
5
+
6
+ # Classes that represent the domain objects in the VOTable 1.1 specification
7
+ # (http://www.ivoa.net/Documents/latest/VOT.html).
8
+ module V1_1
9
+
10
+ # The root element of the votable.
11
+ class VOTable < VORuby::VOTable::Base
12
+ ELEMENT_NAME = 'VOTABLE'
13
+
14
+ def self.serialization_order
15
+ [
16
+ :description, :definitions, :coordinate_systems, :params, :infos, :resources,
17
+ :version, :id
18
+ ]
19
+ end
20
+
21
+ # Create a votable.
22
+ # To parse an existing votable one would normally do this:
23
+ # votable = VOTable.from_file('my_file.xml')
24
+ # but any of the other methods described in VOTable::Base#new are also acceptable:
25
+ # votable = VOTable.new(
26
+ # :version => '1.1',
27
+ # :id => 'votable1',
28
+ # :description => Description.new(:text => 'A test votable'),
29
+ # :resources => [Resource.new(...)]
30
+ # ) # etc.
31
+ #
32
+ # or to create a blank VOTable that you'll build up later:
33
+ # votable = VOTable.new()
34
+ def initialize(defn=nil)
35
+ super(defn)
36
+ self.version = '1.1' if !self.version
37
+ end
38
+
39
+ # Retrieve the version. By default this is '1.1'.
40
+ def version
41
+ self.node['version']
42
+ end
43
+
44
+ # Set the version. Normally you should leave
45
+ # this as 1.1.
46
+ def version=(v)
47
+ @node['version'] = v.to_s
48
+ end
49
+
50
+ def id
51
+ self.node['ID']
52
+ end
53
+
54
+ def id=(i)
55
+ @node['ID'] = i.to_s
56
+ end
57
+
58
+ # Retrieve the description (Description).
59
+ def description
60
+ get_element(Description)
61
+ end
62
+
63
+ # Set the description (Description).
64
+ # votable.description = Description.new(:text => 'A fascinating votable')
65
+ def description=(d)
66
+ set_element(Description, d)
67
+ end
68
+
69
+ # Retrieve the definitions (Definitions).
70
+ # _Deprecated_.
71
+ def definitions
72
+ get_element(Definitions)
73
+ end
74
+
75
+ # Set the definitions (Definitions).
76
+ # _Deprecated_.
77
+ def definitions=(d)
78
+ set_element(Definitions, d)
79
+ end
80
+
81
+ # Retrieve the coordinate systems (Coosys).
82
+ def coordinate_systems
83
+ HomogeneousNodeList.new(self.node, xpath_for(Coosys), Coosys)
84
+ end
85
+
86
+ # Set the coordinate systems.
87
+ # Takes an array of Coosys objects.
88
+ # votable.coordinate_systems = [Coosys.new(), ...]
89
+ def coordinate_systems=(systems)
90
+ self.coordinate_systems.replace(systems)
91
+ end
92
+
93
+ # Retrieve the parameters (Param).
94
+ # Returns a HomogeneousNodeList.
95
+ def params
96
+ HomogeneousNodeList.new(self.node, xpath_for(Param), Param)
97
+ end
98
+
99
+ # Set the parameters.
100
+ # Takes an array of Param objects.
101
+ # votable.params = [Param.new(), ...]
102
+ def params=(parameters)
103
+ self.params.replace(parameters)
104
+ end
105
+
106
+ # Retrieve the information list (Info).
107
+ # Returns a HomogeneousNodeList.
108
+ def infos
109
+ HomogeneousNodeList.new(self.node, xpath_for(Info), Info)
110
+ end
111
+
112
+ # Set the information list.
113
+ # Takes an array of Info objects.
114
+ # votable.infos = [Info.new(), ...]
115
+ def infos=(is)
116
+ self.infos.replace(is)
117
+ end
118
+
119
+ # Retrieve the resources (Resource).
120
+ # Returns a HomogeneousNodeList.
121
+ def resources
122
+ HomogeneousNodeList.new(self.node, xpath_for(Resource), Resource)
123
+ end
124
+
125
+ # Set the resources.
126
+ # Takes an array of Resource objects.
127
+ # votable.resources = [Resource.new(), ...]
128
+ def resources=(res)
129
+ self.resources.replace(res)
130
+ end
131
+
132
+ # Convert a VOTable to HTML.
133
+ # Not all attributes are converted.
134
+ # See test/voruby/votable/1.1/votable.html for an example of the output.
135
+ def to_html
136
+ builder = Builder::XmlMarkup.new(:indent => 2)
137
+
138
+ votable_opts = {:class => 'votable'}
139
+ votable_opts[:id] = self.id if self.id
140
+
141
+ builder.div(votable_opts){ |votable|
142
+ votable.div(self.description.text, :class => 'description') if self.description
143
+
144
+ self.resources.each do |res|
145
+ votable << res.to_html
146
+ end
147
+ }
148
+ end
149
+
150
+ protected
151
+
152
+ def methods_to_test_for_equality
153
+ [
154
+ :version, :id, :description,
155
+ :definitions, :coordinate_systems, :params, :infos, :resources
156
+ ]
157
+ end
158
+ end
159
+
160
+ # A simple description of something.
161
+ class Description < VORuby::VOTable::Base
162
+ ELEMENT_NAME = 'DESCRIPTION'
163
+
164
+ # Create a description.
165
+ # descr = Description.new(:text => 'Hello, world!')
166
+ def initialize(defn=nil)
167
+ super(defn)
168
+ end
169
+
170
+ # Retrieve the actual text of the description.
171
+ def text
172
+ self.node.content
173
+ end
174
+
175
+ # Set the text of the description.
176
+ # descr.text = 'Hello, world!'
177
+ def text=(text)
178
+ @node.content = text
179
+ end
180
+
181
+ protected
182
+
183
+ def methods_to_test_for_equality; [:text] end
184
+ end
185
+
186
+ # Definitions of various values appropriate to the votable.
187
+ # *DEPRECATED*.
188
+ class Definitions < VORuby::VOTable::Base
189
+ ELEMENT_NAME = 'DEFINITIONS'
190
+
191
+ # Create a set of definitions.
192
+ # definitions = Definitions.new(
193
+ # :coordinate_systems => [Coosys.new]
194
+ # :params => [Param.new]
195
+ # )
196
+ def initialize(defn=nil)
197
+ super(defn)
198
+ end
199
+
200
+ # Retrieve the coordinate systems (Coosys).
201
+ # Returns a HomogeneousNodeList.
202
+ def coordinate_systems
203
+ HomogeneousNodeList.new(self.node, xpath_for(Coosys), Coosys)
204
+ end
205
+
206
+ # Set the coordinate systems.
207
+ # Takes an array of Coosys objects.
208
+ # definitions.coordinate_systems = [Coosys.new(), ...]
209
+ def coordinate_systems=(systems)
210
+ self.coordinate_systems.replace(systems)
211
+ end
212
+
213
+ # Retrieve the parameters (Param).
214
+ # Returns a HomogeneousNodeList.
215
+ def params
216
+ HomogeneousNodeList.new(self.node, xpath_for(Param), Param)
217
+ end
218
+
219
+ # Set the parameter list.
220
+ # Takes an array of Param objects.
221
+ # definitions.params = [Param.new(), ...]
222
+ def params=(parameters)
223
+ self.params.replace(parameters)
224
+ end
225
+
226
+ protected
227
+
228
+ def methods_to_test_for_equality
229
+ [:coordinate_systems, :params]
230
+ end
231
+ end
232
+
233
+ # A celestial coordinate system, to which the components of a position on the celestial sphere refer.
234
+ class Coosys < VORuby::VOTable::Base
235
+ ELEMENT_NAME = 'COOSYS'
236
+
237
+ # Create a new coordinate system.
238
+ # coosys = Coosys.new(
239
+ # :id => 'J2000',
240
+ # :equinox => 'J2000.',
241
+ # :epoch => 'J2000.',
242
+ # :system => 'eq_FK5'
243
+ # )
244
+ # The default system is eq_FK5.
245
+ def initialize(defn=nil)
246
+ super(defn)
247
+ self.system = 'eq_FK5' if !self.system
248
+ end
249
+
250
+ def id
251
+ self.node['ID']
252
+ end
253
+
254
+ def id=(i)
255
+ @node['ID'] = i.to_s
256
+ end
257
+
258
+ def equinox
259
+ self.node['equinox']
260
+ end
261
+
262
+ def equinox=(e)
263
+ @node['equinox'] = e.to_s
264
+ end
265
+
266
+ def epoch
267
+ self.node['epoch']
268
+ end
269
+
270
+ def epoch=(e)
271
+ @node['epoch'] = e.to_s
272
+ end
273
+
274
+ def system
275
+ self.node['system']
276
+ end
277
+
278
+ # Set the system.
279
+ # May be one of: eq_FK4, eq_FK5, ICRS,
280
+ # ecl_FK4, ecl_FK5, galactic, supergalactic, xy,
281
+ # barycentric or geo_app.
282
+ def system=(s)
283
+ @node['system'] = s.to_s
284
+ end
285
+
286
+ protected
287
+
288
+ def methods_to_test_for_equality
289
+ [:id, :equinox, :epoch, :system]
290
+ end
291
+ end
292
+
293
+ # A global value associated with (usually) a table.
294
+ class Param < VORuby::VOTable::Base
295
+ include Castable
296
+
297
+ ELEMENT_NAME = 'PARAM'
298
+
299
+ def self.serialization_order
300
+ [
301
+ :description, :values, :links,
302
+ :id, :unit, :datatype, :arraysize, :precision, :width, :ref, :name,
303
+ :ucd, :utype, :value
304
+ ]
305
+ end
306
+
307
+ # Create a new parameter.
308
+ # param = Param.new(
309
+ # :name => 'Telescope',
310
+ # :datatype => 'float',
311
+ # :ucd => 'phys.size;instr.tel',
312
+ # :unit => 'm',
313
+ # :value => '3.6'
314
+ # )
315
+ def initialize(defn=nil)
316
+ super(defn)
317
+ end
318
+
319
+ def id
320
+ self.node['ID']
321
+ end
322
+
323
+ def id=(i)
324
+ @node['ID'] = i.to_s
325
+ end
326
+
327
+ def unit
328
+ self.node['unit']
329
+ end
330
+
331
+ # Set the unit.
332
+ # Units should be of the form outlined by Vizier[http://vizier.u-strasbg.fr/doc/catstd-3.2.htx].
333
+ def unit=(u)
334
+ @node['unit'] = u.to_s
335
+ end
336
+
337
+ def datatype
338
+ self.node['datatype']
339
+ end
340
+
341
+ # Set the datatype.
342
+ # Should be one of: boolean, bit, unsignedByte, short, int, long,
343
+ # char, unicodeChar, float, double, floatComplex, doubleComplex.
344
+ def datatype=(d)
345
+ @node['datatype'] = d.to_s
346
+ end
347
+
348
+ def precision
349
+ self.node['precision']
350
+ end
351
+
352
+ # Set the precision of the value.
353
+ # Should match [EF]?[1-9][0-9]*
354
+ # param.precision = '1'
355
+ def precision=(p)
356
+ @node['precision'] = p.to_s
357
+ end
358
+
359
+ def width
360
+ self.node['width'].to_i
361
+ end
362
+
363
+ # Set the width.
364
+ # Should be an integer.
365
+ # param.width = 2
366
+ def width=(w)
367
+ @node['width'] = w.to_s
368
+ end
369
+
370
+ def ref
371
+ self.node['ref']
372
+ end
373
+
374
+ def ref=(r)
375
+ @node['ref'] = r.to_s
376
+ end
377
+
378
+ def name
379
+ self.node['name']
380
+ end
381
+
382
+ def name=(n)
383
+ @node['name'] = n.to_s
384
+ end
385
+
386
+ def ucd
387
+ self.node['ucd']
388
+ end
389
+
390
+ # Set the unified content descriptor or UCD[http://vizier.u-strasbg.fr/doc/UCD.htx].
391
+ def ucd=(u)
392
+ @node['ucd'] = u.to_s
393
+ end
394
+
395
+ def utype
396
+ self.node['utype']
397
+ end
398
+
399
+ # Set the utype (i.e. the role of the column in the context of an external data model).
400
+ def utype=(u)
401
+ @node['utype'] = u.to_s
402
+ end
403
+
404
+ def arraysize
405
+ self.node['arraysize']
406
+ end
407
+
408
+ # Set the arraysize (if applicable).
409
+ # i.e. *, 8x2
410
+ def arraysize=(a)
411
+ @node['arraysize'] = a.to_s
412
+ end
413
+
414
+ # Retrieve the value of the parameter.
415
+ # If _cast_ is false (default), the value is returned as a simple string.
416
+ # However, if _cast_ is true, the datatype and arraysize are used to
417
+ # determine a suitable object (or list of objects) to return.
418
+ # See Castable#as_obj for more details.
419
+ def value(cast=false)
420
+ cast ? as_obj(self.value, self.datatype, self.arraysize) : self.node['value']
421
+ end
422
+
423
+ # Set the value of the parameter.
424
+ # An attempt is made to convert native ruby types using the datatype and
425
+ # arraysize parameters.
426
+ # param.value = Complex.new(1.1, 2.2) # etc.
427
+ def value=(v)
428
+ @node['value'] = v.is_a?(String) ? v : as_string(v, self.datatype, self.arraysize)
429
+ end
430
+
431
+ # Retrieve the description (Description).
432
+ def description
433
+ get_element(Description)
434
+ end
435
+
436
+ # Set the description (Description).
437
+ def description=(d)
438
+ set_element(Description, d)
439
+ end
440
+
441
+ # Retrieve the values (Values).
442
+ def values
443
+ get_element(Values)
444
+ end
445
+
446
+ # Set the values (Values).
447
+ def values=(v)
448
+ set_element(Values, v)
449
+ end
450
+
451
+ # Retrieve the links.
452
+ # Returns a HomogeneousNodeList object.
453
+ def links
454
+ HomogeneousNodeList.new(self.node, xpath_for(Link), Link)
455
+ end
456
+
457
+ # Set the links.
458
+ # Takes an array of Link objects.
459
+ def links=(lnks)
460
+ self.links.replace(lnks)
461
+ end
462
+
463
+ protected
464
+
465
+ def methods_to_test_for_equality
466
+ [
467
+ :id, :unit, :datatype, :precision, :width, :ref, :name, :ucd, :utype,
468
+ :value, :arraysize,
469
+ :description, :values, :links
470
+ ]
471
+ end
472
+ end
473
+
474
+ # A name-value pair.
475
+ class Info < VORuby::VOTable::Base
476
+ ELEMENT_NAME = 'INFO'
477
+
478
+ # Create a new name-value pair.
479
+ # info = Info.new(:name => 'history', :value => 'my first observation')
480
+ def initialize(defn=nil)
481
+ super(defn)
482
+ end
483
+
484
+ def id
485
+ self.node['ID']
486
+ end
487
+
488
+ def id=(i)
489
+ @node['ID'] = i.to_s
490
+ end
491
+
492
+ def name
493
+ self.node['name']
494
+ end
495
+
496
+ def name=(n)
497
+ @node['name'] = n.to_s
498
+ end
499
+
500
+ def value
501
+ self.node['value']
502
+ end
503
+
504
+ def value=(v)
505
+ @node['value'] = v.to_s
506
+ end
507
+
508
+ protected
509
+
510
+ def methods_to_test_for_equality
511
+ [:id, :name, :value]
512
+ end
513
+ end
514
+
515
+ # A description and the data values of some logically independent data structure
516
+ # within the VOTable.
517
+ class Resource < VORuby::VOTable::Base
518
+ ELEMENT_NAME = 'RESOURCE'
519
+
520
+ def self.serialization_order
521
+ [
522
+ :description, :infos, :coordinate_systems, :params, :links, :tables, :resources,
523
+ :id, :name, :type, :utype
524
+ ]
525
+ end
526
+
527
+ # Create a new resource.
528
+ # res = Resource.new(
529
+ # :name => 'myFavouriteGalaxies',
530
+ # :type => 'meta',
531
+ # :params => [Param.new()],
532
+ # :links => [Link.new()],
533
+ # :tables => [Table.new()]
534
+ # )
535
+ def initialize(defn=nil)
536
+ super(defn)
537
+ end
538
+
539
+ def name
540
+ self.node['name']
541
+ end
542
+
543
+ def name=(n)
544
+ @node['name'] = n.to_s
545
+ end
546
+
547
+ def id
548
+ self.node['ID']
549
+ end
550
+
551
+ def id=(i)
552
+ @node['ID'] = i.to_s
553
+ end
554
+
555
+ # Retrieve the utype.
556
+ def utype
557
+ self.node['utype']
558
+ end
559
+
560
+ # Set the utype (i.e. the role of the column in the context of an external data model).
561
+ def utype=(u)
562
+ @node['utype'] = u.to_s
563
+ end
564
+
565
+ # Retrieve the type.
566
+ # A type of 'meta' means that the resource is descriptive only
567
+ # (does not contain any actual data in any of its sub-elements).
568
+ def type
569
+ self.node['type']
570
+ end
571
+
572
+ # Set the type.
573
+ def type=(t)
574
+ @node['type'] = t.to_s
575
+ end
576
+
577
+ # Retrieve the description (Description).
578
+ def description
579
+ get_element(Description)
580
+ end
581
+
582
+ # Set the description (Description).
583
+ # res.description = Description.new(:text => 'A fascinating resource')
584
+ def description=(d)
585
+ set_element(Description, d)
586
+ end
587
+
588
+ # Retrieve the name-value pairs (Info).
589
+ # Returns a HomogeneousNodeList.
590
+ def infos
591
+ HomogeneousNodeList.new(self.node, xpath_for(Info), Info)
592
+ end
593
+
594
+ # Set any name-value pairs.
595
+ # res.infos = [Info.new(), ...]
596
+ def infos=(is)
597
+ self.infos.replace(is)
598
+ end
599
+
600
+ # Retrieve the coordinate systems (Coosys).
601
+ # Returns a HomogeneousNodeList.
602
+ def coordinate_systems
603
+ HomogeneousNodeList.new(self.node, xpath_for(Coosys), Coosys)
604
+ end
605
+
606
+ # Set the coordinate systems (Coosys).
607
+ # res.coordinate_systems = [Coosys.new(), ...]
608
+ def coordinate_systems=(systems)
609
+ self.coordinate_systems.replace(systems)
610
+ end
611
+
612
+ # Retrieve the parameters (Param).
613
+ # Returns a HomogeneousNodeList.
614
+ def params
615
+ HomogeneousNodeList.new(self.node, xpath_for(Param), Param)
616
+ end
617
+
618
+ # Set the parameters (Param).
619
+ # res.params = [Param.new(), ...]
620
+ def params=(parameters)
621
+ self.params.clear
622
+ parameters.each do |p|
623
+ self.params << p
624
+ end
625
+ end
626
+
627
+ # Retrieve the links (Link).
628
+ # Returns a HomogeneousNodeList.
629
+ def links
630
+ HomogeneousNodeList.new(self.node, xpath_for(Link), Link)
631
+ end
632
+
633
+ # Set the links (Link).
634
+ # res.links = [Link.new(), ...]
635
+ def links=(lnks)
636
+ self.links.replace(lnks)
637
+ end
638
+
639
+ # Retrieve the tables (Table).
640
+ # Returns a HomogeneousNodeList.
641
+ def tables
642
+ HomogeneousNodeList.new(self.node, xpath_for(Table), Table)
643
+ end
644
+
645
+ # Set the tables (Table).
646
+ # res.tables = [Table.new(), ....]
647
+ def tables=(tbls)
648
+ self.tables.replace(tbls)
649
+ end
650
+
651
+ # Retrieve sub-resources (Resource).
652
+ # Returns a HomogeneousNodeList.
653
+ def resources
654
+ HomogeneousNodeList.new(self.node, xpath_for(Resource), Resource)
655
+ end
656
+
657
+ # Set sub-resources.
658
+ # res.resources = [Resource.new(), ...]
659
+ def resources=(res)
660
+ self.resources.replace(res)
661
+ end
662
+
663
+ # Convert a resource to HTML.
664
+ def to_html
665
+ builder = Builder::XmlMarkup.new(:indent => 2, :margin => 1)
666
+
667
+ resource_opts = {:class => 'resource'}
668
+ resource_opts[:id] = self.id if self.id
669
+
670
+ builder.div(resource_opts){ |resource|
671
+ resource.h3(self.name) if self.name
672
+ resource.div(self.description.text, :class => 'description') if self.description
673
+
674
+ self.tables.each do |tbl|
675
+ resource << tbl.to_html
676
+ end
677
+
678
+ self.resources.each do |res|
679
+ resource << res.to_html
680
+ end
681
+ }
682
+ end
683
+
684
+ protected
685
+
686
+ def methods_to_test_for_equality
687
+ [
688
+ :name, :id, :utype, :type,
689
+ :description, :infos, :coordinate_systems, :params,
690
+ :links, :tables, :resources
691
+ ]
692
+ end
693
+ end
694
+
695
+ # A link or pointer to other documents or data servers on the Internet through a URI.
696
+ class Link < VORuby::VOTable::Base
697
+ ELEMENT_NAME = 'LINK'
698
+
699
+ # Create a new link.
700
+ # link = Link.new(
701
+ # :href => 'http://fits.gsfc.nasa.gov/nrao_data/samples/image/swp05569slg.fits',
702
+ # :content_type => 'image/fits'
703
+ # )
704
+ def initialize(defn=nil)
705
+ super(defn)
706
+ end
707
+
708
+ def id
709
+ self.node['ID']
710
+ end
711
+
712
+ def id=(i)
713
+ @node['ID'] = i.to_s
714
+ end
715
+
716
+ def content_role
717
+ self.node['content-role']
718
+ end
719
+
720
+ # Set the content role.
721
+ # May be one of: query, hints, doc or location.
722
+ def content_role=(c)
723
+ @node['content-role'] = c.to_s
724
+ end
725
+
726
+ def content_type
727
+ self.node['content-type']
728
+ end
729
+
730
+ # Set the content type (i.e. mimetype).
731
+ def content_type=(c)
732
+ @node['content-type'] = c.to_s
733
+ end
734
+
735
+ def title
736
+ self.node['title']
737
+ end
738
+
739
+ def title=(t)
740
+ @node['title'] = t.to_s
741
+ end
742
+
743
+ def value
744
+ self.node['value']
745
+ end
746
+
747
+ def value=(v)
748
+ @node['value'] = v.to_s
749
+ end
750
+
751
+ # Retrieve the URL.
752
+ # Returns a URI object.
753
+ def href
754
+ self.node['href'] ? URI.parse(self.node['href']) : nil
755
+ end
756
+
757
+ # Set the URL.
758
+ # link.href = 'http://www.noao.edu/' # or...
759
+ # link.href = URI.parse('http://www.noao.edu/')
760
+ def href=(h)
761
+ @node['href'] = h.to_s
762
+ end
763
+
764
+ # *DEPRECATED*.
765
+ def gref
766
+ self.node['gref']
767
+ end
768
+
769
+ # *DEPRECATED*.
770
+ def gref=(g)
771
+ @node['gref'] = g.to_s
772
+ end
773
+
774
+ # Retrieve the action.
775
+ # Returns a URI object.
776
+ def action
777
+ self.node['action'] ? URI.parse(self.node['action']) : nil
778
+ end
779
+
780
+ # Set the action.
781
+ # link.action = 'http://www.retrieve-me.com/' # or...
782
+ # link.action = URI.parse('http://www.retrieve-me.com/')
783
+ def action=(a)
784
+ @node['action'] = a.to_s
785
+ end
786
+
787
+ # Retrieve the link.
788
+ # Understands any URL groked by open-uri (including file://).
789
+ # Returns a File object.
790
+ def retrieve
791
+ shref = self.href
792
+
793
+ if shref
794
+ shref.scheme == 'file' ? File.open(shref.path) : open(shref.to_s)
795
+ else
796
+ nil
797
+ end
798
+ end
799
+
800
+ protected
801
+
802
+ def methods_to_test_for_equality
803
+ [
804
+ :id, :content_role, :content_type, :title, :value,
805
+ :href, :gref, :action
806
+ ]
807
+ end
808
+ end
809
+
810
+ # The basic structure of a votable. Essentially, tablular data +
811
+ # a description of the columns of that data.
812
+ class Table < VORuby::VOTable::Base
813
+ ELEMENT_NAME= 'TABLE'
814
+
815
+ def self.serialization_order
816
+ [
817
+ :description, :params, :fields, :groups, :links, :data,
818
+ :id, :name, :ucd, :utype, :ref, :nrows
819
+ ]
820
+ end
821
+
822
+ # Create a new table.
823
+ # table = Table.new(
824
+ # :name => 'results',
825
+ # :fields => [Field.new()],
826
+ # :data => Data.new(:format => TableData.new())
827
+ # )
828
+ def initialize(defn=nil)
829
+ super(defn)
830
+ end
831
+
832
+ def id
833
+ self.node['ID']
834
+ end
835
+
836
+ def id=(i)
837
+ @node['ID'] = i.to_s
838
+ end
839
+
840
+ def name
841
+ self.node['name']
842
+ end
843
+
844
+ def name=(n)
845
+ @node['name'] = n.to_s
846
+ end
847
+
848
+ def ref
849
+ self.node['ref']
850
+ end
851
+
852
+ def ref=(r)
853
+ @node['ref'] = r.to_s
854
+ end
855
+
856
+ def ucd
857
+ self.node['ucd']
858
+ end
859
+
860
+ # Set the unified content descriptor or UCD[http://vizier.u-strasbg.fr/doc/UCD.htx].
861
+ def ucd=(u)
862
+ @node['ucd'] = u.to_s
863
+ end
864
+
865
+ def utype
866
+ self.node['utype']
867
+ end
868
+
869
+ # Set the utype (i.e. the role of the column in the context of an external data model).
870
+ def utype=(u)
871
+ @node['utype'] = u.to_s
872
+ end
873
+
874
+ # Retrieve the number of rows in the table.
875
+ def nrows
876
+ self.node['nrows'] ? self.node['nrows'].to_i : nil
877
+ end
878
+
879
+ # Set the number of rows in the table.
880
+ # _n_ should be an integer.
881
+ def nrows=(n)
882
+ @node['nrows'] = n.to_s
883
+ end
884
+
885
+ # Retrieve the description (Description).
886
+ def description
887
+ get_element(Description)
888
+ end
889
+
890
+ # Set the description (Description).
891
+ def description=(d)
892
+ set_element(Description, d)
893
+ end
894
+
895
+ # Retrieve the data (Data).
896
+ def data
897
+ get_element(Data)
898
+ end
899
+
900
+ # Set the data (Data).
901
+ def data=(d)
902
+ set_element(Data, d)
903
+ end
904
+
905
+ # Retrieve the fields (Field), a.k.a. column descriptions.
906
+ # Returns a HomogeneousNodeList.
907
+ def fields
908
+ HomogeneousNodeList.new(self.node, xpath_for(Field), Field)
909
+ end
910
+
911
+ # Set the fields.
912
+ # table.fields = [Field.new(), ...]
913
+ def fields=(flds)
914
+ self.fields.replace(flds)
915
+ end
916
+
917
+ # Retrieve the parameters (Param).
918
+ # Returns a HomogeneousNodeList.
919
+ def params
920
+ HomogeneousNodeList.new(self.node, xpath_for(Param), Param)
921
+ end
922
+
923
+ # Set the parameters list (Param).
924
+ # table.params = [Param.new(), ...]
925
+ def params=(parameters)
926
+ self.params.replace(parameters)
927
+ end
928
+
929
+ # Retrieve the groups (Group).
930
+ # Returns a HomogeneousNodeList.
931
+ def groups
932
+ HomogeneousNodeList.new(self.node, xpath_for(Group), Group)
933
+ end
934
+
935
+ # Set the groups (Group).
936
+ # table.groups = [Group.new(), ...]
937
+ def groups=(grps)
938
+ self.groups.replace(grps)
939
+ end
940
+
941
+ # Retrieve the links (Link).
942
+ # Returns a HomogeneousNodeList.
943
+ def links
944
+ HomogeneousNodeList.new(self.node, xpath_for(Link), Link)
945
+ end
946
+
947
+ # Set the links (Link).
948
+ # table.links = [Link.new(), ...]
949
+ def links=(lnks)
950
+ self.links.replace(lnks)
951
+ end
952
+
953
+ # Convert the table into HTML.
954
+ # Not all aspects of the votable are translated.
955
+ # table = Table.new(
956
+ # :id => 'table1',
957
+ # :description => Description.new(:text => 'A test table'),
958
+ # :fields => [
959
+ # Field.new(:name => 'RA', :id => 'col1', :ucd => 'pos.eq.ra;meta.main',
960
+ # :ref => 'J2000', :datatype => 'float', :width => 6, :precision => '2', :unit => 'deg'),
961
+ # Field.new(:name => 'Dec', :id => 'col2', :ucd => 'pos.eq.dec;meta.main',
962
+ # :ref => 'J2000', :datatype => 'float', :width => 6, :precision => '2', :unit => 'deg'),
963
+ # Field.new(:name => 'Name', :id => 'col3', :ucd => 'meta.id;meta.main',
964
+ # :datatype => 'char', :arraysize => '8*')
965
+ # ],
966
+ # :data => Data.new(
967
+ # :format => TableData.new(
968
+ # :trs => [
969
+ # Tr.new(:tds => [Td.new(:text => '123'), Td.new(:text => '456'), Td.new(:text => 'my_obj1')]),
970
+ # Tr.new(:tds => [Td.new(:text => '789'), Td.new(:text => '112'), Td.new(:text => 'my_obj2')]),
971
+ # Tr.new(:tds => [Td.new(:text => '145'), Td.new(:text => '178'), Td.new(:text => 'my_obj3')])
972
+ # ]
973
+ # )
974
+ # )
975
+ # )
976
+ #
977
+ # puts table.to_html # =>
978
+ # <table id="table1">
979
+ # <caption>A test table</caption>
980
+ # <thead>
981
+ # <tr>
982
+ # <th>
983
+ # <div class="field" id="col1">
984
+ # <div class="name">RA</div>
985
+ # <div class="ucd">pos.eq.ra;meta.main</div>
986
+ # <div class="unit">deg</div>
987
+ # <span class="datatype">float</span>
988
+ # </div>
989
+ # </th>
990
+ # <th>
991
+ # <div class="field" id="col2">
992
+ # <div class="name">Dec</div>
993
+ # <div class="ucd">pos.eq.dec;meta.main</div>
994
+ # <div class="unit">deg</div>
995
+ # <span class="datatype">float</span>
996
+ # </div>
997
+ # </th>
998
+ # <th>
999
+ # <div class="field" id="col3">
1000
+ # <div class="name">Name</div>
1001
+ # <div class="ucd">meta.id;meta.main</div>
1002
+ # <span class="datatype">char</span>
1003
+ # <span class="arraysize">8*</span>
1004
+ # </div>
1005
+ # </th>
1006
+ # </tr>
1007
+ # </thead>
1008
+ # <tbody>
1009
+ # <tr>
1010
+ # <td>123</td>
1011
+ # <td>456</td>
1012
+ # <td>my_obj1</td>
1013
+ # </tr>
1014
+ # <tr>
1015
+ # <td>789</td>
1016
+ # <td>112</td>
1017
+ # <td>my_obj2</td>
1018
+ # </tr>
1019
+ # <tr>
1020
+ # <td>145</td>
1021
+ # <td>178</td>
1022
+ # <td>my_obj3</td>
1023
+ # </tr>
1024
+ # </tbody>
1025
+ # </table
1026
+ def to_html
1027
+ builder = Builder::XmlMarkup.new(:indent => 2, :margin => 2)
1028
+
1029
+ tbl_options = {}
1030
+ tbl_options[:id] = self.id if self.id
1031
+
1032
+ builder.table(tbl_options) { |table|
1033
+ table.caption(self.description.text) if self.description
1034
+
1035
+ table.thead { |thead|
1036
+ if self.fields.size > 0
1037
+ thead.tr { |tr|
1038
+ self.fields.each do |field|
1039
+ tr.th { |th|
1040
+ th << field.to_html
1041
+ }
1042
+ end
1043
+ }
1044
+ end
1045
+ }
1046
+
1047
+ if self.data and self.data.format
1048
+ table.tbody { |tbody|
1049
+ self.data.format.trs.each do |tr|
1050
+ tbody << tr.to_html
1051
+ end
1052
+ }
1053
+ end
1054
+ }
1055
+ end
1056
+
1057
+ protected
1058
+
1059
+ def methods_to_test_for_equality
1060
+ [
1061
+ :id, :name, :ref, :ucd, :utype, :nrows,
1062
+ :description, :data, :fields, :params, :groups,
1063
+ :links
1064
+ ]
1065
+ end
1066
+ end
1067
+
1068
+ # The description of an actual table column.
1069
+ class Field < VORuby::VOTable::Base
1070
+ ELEMENT_NAME = 'FIELD'
1071
+
1072
+ def self.serialization_order
1073
+ [
1074
+ :description, :values, :links,
1075
+ :id, :unit, :datatype, :precision, :width, :ref,
1076
+ :name, :ucd, :utype, :arraysize, :type
1077
+ ]
1078
+ end
1079
+
1080
+ # Create a new table column description.
1081
+ # field = Field.new(
1082
+ # :name => 'RA',
1083
+ # :id => 'col1',
1084
+ # :ucd => 'pos.eq.ra;meta.main',
1085
+ # :ref => 'J2000',
1086
+ # :datatype => 'float',
1087
+ # :width => 6,
1088
+ # :precision => '2',
1089
+ # :unit => 'deg'
1090
+ # )
1091
+ def initialize(defn=nil)
1092
+ super(defn)
1093
+ end
1094
+
1095
+ def id
1096
+ self.node['ID']
1097
+ end
1098
+
1099
+ def id=(i)
1100
+ @node['ID'] = i.to_s
1101
+ end
1102
+
1103
+ def unit
1104
+ self.node['unit']
1105
+ end
1106
+
1107
+ # Set the unit.
1108
+ # Units should be of the form outlined by Vizier[http://vizier.u-strasbg.fr/doc/catstd-3.2.htx].
1109
+ def unit=(u)
1110
+ @node['unit'] = u.to_s
1111
+ end
1112
+
1113
+ def datatype
1114
+ self.node['datatype']
1115
+ end
1116
+
1117
+ # Set the datatype.
1118
+ # Should be one of: boolean, bit, unsignedByte, short, int, long,
1119
+ # char, unicodeChar, float, double, floatComplex, doubleComplex.
1120
+ def datatype=(d)
1121
+ @node['datatype'] = d.to_s
1122
+ end
1123
+
1124
+ def precision
1125
+ self.node['precision']
1126
+ end
1127
+
1128
+ # Set the precision of the value.
1129
+ # Should match [EF]?[1-9][0-9]*
1130
+ # param.precision = '1'
1131
+ def precision=(p)
1132
+ @node['precision'] = p.to_s
1133
+ end
1134
+
1135
+ def width
1136
+ self.node['width'] ? self.node['width'].to_i : nil
1137
+ end
1138
+
1139
+ # Set the width.
1140
+ # Should be an integer.
1141
+ # param.width = 2
1142
+ def width=(w)
1143
+ @node['width'] = w.to_s
1144
+ end
1145
+
1146
+ def ref
1147
+ self.node['ref']
1148
+ end
1149
+
1150
+ def ref=(r)
1151
+ @node['ref'] = r.to_s
1152
+ end
1153
+
1154
+ def name
1155
+ self.node['name']
1156
+ end
1157
+
1158
+ def name=(n)
1159
+ @node['name'] = n.to_s
1160
+ end
1161
+
1162
+ def ucd
1163
+ self.node['ucd']
1164
+ end
1165
+
1166
+ # Set the unified content descriptor or UCD[http://vizier.u-strasbg.fr/doc/UCD.htx].
1167
+ def ucd=(u)
1168
+ @node['ucd'] = u.to_s
1169
+ end
1170
+
1171
+ def utype
1172
+ self.node['utype']
1173
+ end
1174
+
1175
+ # Set the utype (i.e. the role of the column in the context of an external data model).
1176
+ def utype=(u)
1177
+ @node['utype'] = u.to_s
1178
+ end
1179
+
1180
+ def arraysize
1181
+ self.node['arraysize']
1182
+ end
1183
+
1184
+ # Set the arraysize (if applicable).
1185
+ # i.e. *, 8x2
1186
+ def arraysize=(a)
1187
+ @node['arraysize'] = a.to_s
1188
+ end
1189
+
1190
+ # *DEPRECATED*
1191
+ def type
1192
+ self.node['type']
1193
+ end
1194
+
1195
+ # May be on of: hidden, no_query, trigger or location.
1196
+ # *DEPRECATED*
1197
+ def type=(t)
1198
+ @node['type'] = t.to_s
1199
+ end
1200
+
1201
+ # Retrieve the description (Description).
1202
+ def description
1203
+ get_element(Description)
1204
+ end
1205
+
1206
+ # Set the description (Description).
1207
+ def description=(d)
1208
+ set_element(Description, d)
1209
+ end
1210
+
1211
+ # Retrieve the values (Values).
1212
+ def values
1213
+ HomogeneousNodeList.new(self.node, xpath_for(Values), Values)
1214
+ end
1215
+
1216
+ # Set the values (Values).
1217
+ def values=(vals)
1218
+ self.values.replace(vals)
1219
+ end
1220
+
1221
+ # Retrieve the links.
1222
+ # Returns a HomogeneousNodeList object.
1223
+ def links
1224
+ HomogeneousNodeList.new(self.node, xpath_for(Link), Link)
1225
+ end
1226
+
1227
+ # Set the links.
1228
+ # Takes an array of Link objects.
1229
+ def links=(lnks)
1230
+ self.links.replace(lnks)
1231
+ end
1232
+
1233
+ # Convert a field to HTML.
1234
+ def to_html
1235
+ builder = Builder::XmlMarkup.new(:indent => 2, :margin => 6)
1236
+
1237
+ field_opts = {:class => 'field'}
1238
+ field_opts[:id] = self.id if self.id
1239
+
1240
+ builder.div(field_opts) { |field|
1241
+ field.div(self.name, :class => 'name')
1242
+ field.div(self.ucd, :class => 'ucd') if self.ucd
1243
+ field.div(self.utype, :class => 'utype') if self.utype
1244
+ field.div(self.unit, :class => 'unit') if self.unit
1245
+ field.span(self.datatype, :class => 'datatype') if self.datatype
1246
+ field.span(self.arraysize, :class => 'arraysize') if self.arraysize
1247
+ }
1248
+ end
1249
+
1250
+ protected
1251
+
1252
+ def methods_to_test_for_equality
1253
+ [
1254
+ :id, :unit, :datatype, :precision, :width, :ref,
1255
+ :name, :ucd, :utype, :arraysize, :type,
1256
+ :description, :values, :links
1257
+ ]
1258
+ end
1259
+ end
1260
+
1261
+ # Holds subsidiary information about the domain of the data.
1262
+ class Values < VORuby::VOTable::Base
1263
+ ELEMENT_NAME = 'VALUES'
1264
+
1265
+ def self.serialization_order
1266
+ [
1267
+ :min, :max, :options,
1268
+ :id, :type, :null, :ref
1269
+ ]
1270
+ end
1271
+
1272
+ # Create some new subsidiary information about the domain.
1273
+ # values = Values.new(
1274
+ # :id => 'RAdomain',
1275
+ # :min => Min.new(:value => '0'),
1276
+ # :max => Max.new(:value => '360', :inclusive => false)
1277
+ # )
1278
+ def initialize(defn=nil)
1279
+ super(defn)
1280
+ self.type = 'legal' if !self.type
1281
+ end
1282
+
1283
+ def id
1284
+ self.node['ID']
1285
+ end
1286
+
1287
+ def id=(i)
1288
+ @node['ID'] = i.to_s
1289
+ end
1290
+
1291
+ def type
1292
+ self.node['type']
1293
+ end
1294
+
1295
+ # Set the scope of values present.
1296
+ # Possible values are: legal, actual.
1297
+ # Defaults to legal.
1298
+ def type=(t)
1299
+ @node['type'] = t.to_s
1300
+ end
1301
+
1302
+ def null
1303
+ self.node['null']
1304
+ end
1305
+
1306
+ # Set the value that is used to specify
1307
+ # non-existent data.
1308
+ def null=(n)
1309
+ @node['null'] = n.to_s
1310
+ end
1311
+
1312
+ def ref
1313
+ self.node['ref']
1314
+ end
1315
+
1316
+ def ref=(r)
1317
+ @node['ref'] = r.to_s
1318
+ end
1319
+
1320
+ # Retrieve the maximum of the value (Max).
1321
+ def max
1322
+ get_element(Max)
1323
+ end
1324
+
1325
+ # Set the maximum of the value (Max).
1326
+ def max=(m)
1327
+ set_element(Max, m)
1328
+ end
1329
+
1330
+ # Retrieve the minimum of the value (Min).
1331
+ def min
1332
+ get_element(Min)
1333
+ end
1334
+
1335
+ # Set the minimum of the value (Min).
1336
+ def min=(m)
1337
+ set_element(Min, m)
1338
+ end
1339
+
1340
+ # Retrieve the possible values (Option) the column can take on.
1341
+ # Returns a HomogeneousNodeList object.
1342
+ def options
1343
+ HomogeneousNodeList.new(self.node, xpath_for(Option), Option)
1344
+ end
1345
+
1346
+ # Set the possible values the column can take on.
1347
+ # values.options = [Option.new(), ...]
1348
+ def options=(opts)
1349
+ self.options.replace(opts)
1350
+ end
1351
+
1352
+ protected
1353
+
1354
+ def methods_to_test_for_equality
1355
+ [
1356
+ :id, :type, :null, :ref,
1357
+ :max, :min, :options
1358
+ ]
1359
+ end
1360
+ end
1361
+
1362
+ # A minimum value a column can take on.
1363
+ class Min < VORuby::VOTable::Base
1364
+ ELEMENT_NAME = 'MIN'
1365
+
1366
+ # Create a new minimum value for a column.
1367
+ # min = Min.new(:value => '0')
1368
+ def initialize(defn=nil)
1369
+ super(defn)
1370
+ self.inclusive = true if !self.inclusive
1371
+ end
1372
+
1373
+ def value
1374
+ self.node['value']
1375
+ end
1376
+
1377
+ def value=(v)
1378
+ @node['value'] = v.to_s
1379
+ end
1380
+
1381
+ def inclusive
1382
+ self.node['inclusive']
1383
+ end
1384
+
1385
+ # Check whether the minimum value is inclusive or not.
1386
+ # By default, the minimum is inclusive.
1387
+ def inclusive?
1388
+ self.node['inclusive'] == 'yes'
1389
+ end
1390
+
1391
+ # Set whether the minimum value is inclusive or not.
1392
+ # Takes a boolean value or a yes/no string.
1393
+ # min.inclusive = false # or...
1394
+ # min.inclusive = 'no'
1395
+ def inclusive=(i)
1396
+ if i.is_a?(TrueClass)
1397
+ @node['inclusive'] = 'yes'
1398
+ elsif i.is_a?(FalseClass)
1399
+ @node['inclusive'] = 'no'
1400
+ else
1401
+ @node['inclusive'] = i.to_s
1402
+ end
1403
+ end
1404
+
1405
+ protected
1406
+
1407
+ def methods_to_test_for_equality
1408
+ [:value, :inclusive]
1409
+ end
1410
+ end
1411
+
1412
+ # The maximum value a column may take on.
1413
+ class Max < VORuby::VOTable::Base
1414
+ ELEMENT_NAME = 'MAX'
1415
+
1416
+ # Create a new maximum value for a column.
1417
+ # max = Max.new(:value => '360', :inclusive => false)
1418
+ def initialize(defn=nil)
1419
+ super(defn)
1420
+ self.inclusive = true if !self.inclusive
1421
+ end
1422
+
1423
+ def value
1424
+ self.node['value']
1425
+ end
1426
+
1427
+ def value=(v)
1428
+ @node['value'] = v.to_s
1429
+ end
1430
+
1431
+ def inclusive
1432
+ self.node['inclusive']
1433
+ end
1434
+
1435
+ # Check whether the maximum value is inclusive or not.
1436
+ # By default, the maximum is inclusive.
1437
+ def inclusive?
1438
+ self.node['inclusive'] == 'yes'
1439
+ end
1440
+
1441
+ # Set whether the maximum value is inclusive or not.
1442
+ # Takes a boolean value or a yes/no string.
1443
+ # max.inclusive = false # or...
1444
+ # max.inclusive = 'no'
1445
+ def inclusive=(i)
1446
+ if i.is_a?(TrueClass)
1447
+ @node['inclusive'] = 'yes'
1448
+ elsif i.is_a?(FalseClass)
1449
+ @node['inclusive'] = 'no'
1450
+ else
1451
+ @node['inclusive'] = i.to_s
1452
+ end
1453
+ end
1454
+
1455
+ protected
1456
+
1457
+ def methods_to_test_for_equality
1458
+ [:value, :inclusive]
1459
+ end
1460
+ end
1461
+
1462
+ # An enumeration of possible values.
1463
+ # Essentially a hierarchy of key-value pairs.
1464
+ class Option < VORuby::VOTable::Base
1465
+ ELEMENT_NAME = 'OPTION'
1466
+
1467
+ # Create a new enumeration.
1468
+ # option = Option.new(
1469
+ # :name => 'authors',
1470
+ # :options => [
1471
+ # Option.new(:name => 'last_name', :value => 'Gasson'),
1472
+ # Option.new(:name => 'last_name', :value => 'Miller')
1473
+ # ]
1474
+ # )
1475
+ def initialize(defn=nil)
1476
+ super(defn)
1477
+ end
1478
+
1479
+ def name
1480
+ self.node['name']
1481
+ end
1482
+
1483
+ def name=(n)
1484
+ @node['name'] = n.to_s
1485
+ end
1486
+
1487
+ def value
1488
+ self.node['value']
1489
+ end
1490
+
1491
+ def value=(v)
1492
+ @node['value'] = v.to_s
1493
+ end
1494
+
1495
+ # Retrieve any sub-options (Option).
1496
+ # Returns a HomogeneousNodeList.
1497
+ def options
1498
+ HomogeneousNodeList.new(self.node, xpath_for(Option), Option)
1499
+ end
1500
+
1501
+ # Set any sub-options.
1502
+ # option.options = [Option.new(), ...]
1503
+ def options=(opts)
1504
+ self.options.replace(opts)
1505
+ end
1506
+
1507
+ protected
1508
+
1509
+ def methods_to_test_for_equality
1510
+ [:name, :value, :options]
1511
+ end
1512
+ end
1513
+
1514
+ # A way of grouping fields which are logically connected, like
1515
+ # a value and its error.
1516
+ class Group < VORuby::VOTable::Base
1517
+ ELEMENT_NAME = 'GROUP'
1518
+
1519
+ def self.serialization_order
1520
+ [
1521
+ :description, :field_refs, :params, :param_refs, :groups,
1522
+ :id, :name, :ref, :ucd, :utype
1523
+ ]
1524
+ end
1525
+
1526
+ # Create a new group.
1527
+ # group = Group.new(
1528
+ # :name => 'Velocity',
1529
+ # :description => Description.new(:text => 'Velocity and its error')
1530
+ # :field_refs => [FieldRef.new(:ref => 'col4'), FieldRef.new(:ref => 'col5')]
1531
+ # )
1532
+ def initialize(defn=nil)
1533
+ super(defn)
1534
+ end
1535
+
1536
+ def id
1537
+ self.node['ID']
1538
+ end
1539
+
1540
+ def id=(i)
1541
+ @node['ID'] = i.to_s
1542
+ end
1543
+
1544
+ def name
1545
+ self.node['name']
1546
+ end
1547
+
1548
+ def name=(n)
1549
+ @node['name'] = n.to_s
1550
+ end
1551
+
1552
+ def ref
1553
+ self.node['ref']
1554
+ end
1555
+
1556
+ def ref=(r)
1557
+ @node['ref'] = r.to_s
1558
+ end
1559
+
1560
+ def ucd
1561
+ self.node['ucd']
1562
+ end
1563
+
1564
+ # Set the unified content descriptor or UCD[http://vizier.u-strasbg.fr/doc/UCD.htx].
1565
+ def ucd=(u)
1566
+ @node['ucd'] = u.to_s
1567
+ end
1568
+
1569
+ def utype
1570
+ self.node['utype']
1571
+ end
1572
+
1573
+ # Set the utype (i.e. the role of the column in the context of an external data model).
1574
+ def utype=(u)
1575
+ @node['utype'] = u.to_s
1576
+ end
1577
+
1578
+ # Retrieve the description (Description).
1579
+ def description
1580
+ get_element(Description)
1581
+ end
1582
+
1583
+ # Set the description (Description).
1584
+ def description=(d)
1585
+ set_element(Description, d)
1586
+ end
1587
+
1588
+ # Retrieve the references to fields.
1589
+ # Returns a HomogeneousNodeList.
1590
+ def field_refs
1591
+ HomogeneousNodeList.new(self.node, xpath_for(FieldRef), FieldRef)
1592
+ end
1593
+
1594
+ # Set the references to fields.
1595
+ # group.field_refs = [FieldRef.new(), ...]
1596
+ def field_refs=(refs)
1597
+ self.field_refs.replace(refs)
1598
+ end
1599
+
1600
+ # Retrieve the references to parameters.
1601
+ # Returns a HomogeneousNodeList.
1602
+ def param_refs
1603
+ HomogeneousNodeList.new(self.node, xpath_for(ParamRef), ParamRef)
1604
+ end
1605
+
1606
+ # Set the the references to parameters.
1607
+ # group.param_refs = [ParamRef.new(), ...]
1608
+ def param_refs=(refs)
1609
+ self.param_refs.replace(refs)
1610
+ end
1611
+
1612
+ # Retrieve the list of parameters.
1613
+ # Normally one would use #param_refs instead.
1614
+ # Returns a HomogeneousNodeList.
1615
+ def params
1616
+ HomogeneousNodeList.new(self.node, xpath_for(Param), Param)
1617
+ end
1618
+
1619
+ # Set the list parameters.
1620
+ # Normally one would use #param_refs= instead.
1621
+ # group.params = [Param.new(), ...]
1622
+ def params=(parameters)
1623
+ self.params.replace(parameters)
1624
+ end
1625
+
1626
+ # Retrieve any sub-groups.
1627
+ # Returns a HomogeneousNodeList.
1628
+ def groups
1629
+ HomogeneousNodeList.new(self.node, xpath_for(Group), Group)
1630
+ end
1631
+
1632
+ # Set any sub-groups.
1633
+ # group.groups = [Group.new(), ...]
1634
+ def groups=(grps)
1635
+ self.groups.replace(grps)
1636
+ end
1637
+
1638
+ protected
1639
+
1640
+ def methods_to_test_for_equality
1641
+ [
1642
+ :id, :name, :ref, :ucd, :utype,
1643
+ :description, :field_refs, :param_refs,
1644
+ :params, :groups
1645
+ ]
1646
+ end
1647
+ end
1648
+
1649
+ # A reference to an existing Field.
1650
+ class FieldRef < VORuby::VOTable::Base
1651
+ ELEMENT_NAME = 'FIELDref'
1652
+
1653
+ # Create a new field reference.
1654
+ # fref = FieldRef.new(:ref => 'col3')
1655
+ def initialize(defn=nil)
1656
+ super(defn)
1657
+ end
1658
+
1659
+ def ref
1660
+ self.node['ref']
1661
+ end
1662
+
1663
+ def ref=(r)
1664
+ @node['ref'] = r.to_s
1665
+ end
1666
+
1667
+ # Retrieve the field (Field) associated with this reference.
1668
+ def field
1669
+ field_node = self.node.find_first("ancestor::*/FIELD[@ID='#{self.ref}']")
1670
+ field_node ? Field.new(field_node) : nil
1671
+ end
1672
+
1673
+ protected
1674
+
1675
+ def methods_to_test_for_equality; [:ref] end
1676
+ end
1677
+
1678
+ # A reference to an existing Param.
1679
+ class ParamRef < VORuby::VOTable::Base
1680
+ ELEMENT_NAME = 'PARAMref'
1681
+
1682
+ # Create an new parameter reference.
1683
+ # pref = ParamRef.new(:ref => 'param1')
1684
+ def initialize(defn=nil)
1685
+ super(defn)
1686
+ end
1687
+
1688
+ def ref
1689
+ self.node['ref']
1690
+ end
1691
+
1692
+ def ref=(r)
1693
+ @node['ref'] = r.to_s
1694
+ end
1695
+
1696
+ # Retrieve the parameter (Param) associated with the reference.
1697
+ def param
1698
+ param_node = self.node.find_first("ancestor::*/PARAM[@ID='#{self.ref}']")
1699
+ param_node ? Param.new(param_node) : nil
1700
+ end
1701
+
1702
+ protected
1703
+
1704
+ def methods_to_test_for_equality; [:ref] end
1705
+ end
1706
+
1707
+ # The actual tabular data.
1708
+ class Data < VORuby::VOTable::Base
1709
+ ELEMENT_NAME = 'DATA'
1710
+
1711
+ # Create a new body of data.
1712
+ # data = Data.new(:format => TableData.new())
1713
+ def initialize(defn=nil)
1714
+ super(defn)
1715
+ end
1716
+
1717
+ # Retrieve the formatted data. May be TableData, Binary or Fits.
1718
+ def format
1719
+ format_node = self.node.find_first("#{xpath_for(TableData)}|#{xpath_for(Binary)}|#{xpath_for(Fits)}")
1720
+ return nil if !format_node
1721
+
1722
+ case format_node.name
1723
+ when 'TABLEDATA' then TableData.new(format_node)
1724
+ when 'BINARY' then Binary.new(format_node)
1725
+ when 'FITS' then Fits.new(format_node)
1726
+ else nil
1727
+ end
1728
+ end
1729
+
1730
+ # Set the formatted data. Must be one of the allowed
1731
+ # data formats--TableData, Binary or Fits.
1732
+ def format=(f)
1733
+ raise 'Data format must be one of TableData, Binary or Fits' if ![TableData, Binary, Fits].include?(f.class)
1734
+
1735
+ self.node.each_child do |c|
1736
+ c.remove!
1737
+ end
1738
+ set_element(f.class, f)
1739
+ end
1740
+
1741
+ protected
1742
+
1743
+ def methods_to_test_for_equality; [:format] end
1744
+ end
1745
+
1746
+ # The most typical way of representing tabular data.
1747
+ class TableData < VORuby::VOTable::Base
1748
+ ELEMENT_NAME = 'TABLEDATA'
1749
+
1750
+ # Create new table data.
1751
+ # tabledata = TableData.new(:trs => [Tr.new, Tr.new, Tr.new])
1752
+ def initialize(defn=nil)
1753
+ super(defn)
1754
+ end
1755
+
1756
+ # Retrieve the rows of data.
1757
+ # Returns a HomogeneousNodeList.
1758
+ def trs
1759
+ HomogeneousNodeList.new(self.node, xpath_for(Tr), Tr)
1760
+ end
1761
+
1762
+ # Set the rows of data.
1763
+ # tabledata.rows = [Tr.new(), ...]
1764
+ def trs=(rows)
1765
+ self.trs.replace(rows)
1766
+ end
1767
+
1768
+ protected
1769
+
1770
+ def methods_to_test_for_equality; [:trs] end
1771
+ end
1772
+
1773
+ # Tabular data represented as a binary format.
1774
+ class Binary < VORuby::VOTable::Base
1775
+ ELEMENT_NAME = 'BINARY'
1776
+
1777
+ # Create a new binary table.
1778
+ # binary = Binary.new(:stream => Stream.new())
1779
+ def initialize(defn=nil)
1780
+ super(defn)
1781
+ end
1782
+
1783
+ # Retrieve the stream (Stream) representing the data.
1784
+ def stream
1785
+ get_element(Stream)
1786
+ end
1787
+
1788
+ # Set the stream representing the data.
1789
+ # binary.stream = Stream.new()
1790
+ def stream=(s)
1791
+ set_element(Stream, s)
1792
+ end
1793
+
1794
+ protected
1795
+
1796
+ def methods_to_test_for_equality; [:stream] end
1797
+ end
1798
+
1799
+ # Represents a stream of bytes, either local or remote.
1800
+ class Stream < VORuby::VOTable::Base
1801
+ ELEMENT_NAME = 'STREAM'
1802
+
1803
+ # Create a new retrieval stream.
1804
+ # stream = Stream.new(:href => 'ftp://server.com/mydata.dat')
1805
+ def initialize(defn=nil)
1806
+ super(defn)
1807
+ self.type = 'locator' if !self.type
1808
+ self.actuate = 'onRequest' if !self.actuate
1809
+ self.encoding = 'none' if !self.encoding
1810
+ end
1811
+
1812
+ def type
1813
+ self.node['type']
1814
+ end
1815
+
1816
+ # Set the type of stream. May be one of: locator or other.
1817
+ # Default is locator.
1818
+ def type=(t)
1819
+ @node['type'] = t.to_s
1820
+ end
1821
+
1822
+ # Retrieve the URL of the stream.
1823
+ # Returns a URI object.
1824
+ def href
1825
+ self.node['href'] ? URI.parse(self.node['href']) : nil
1826
+ end
1827
+
1828
+ # Set the URL of the stream.
1829
+ # link.href = 'http://www.noao.edu/my.dat' # or...
1830
+ # link.href = URI.parse('http://www.noao.edu/my.dat')
1831
+ def href=(h)
1832
+ @node['href'] = h.to_s
1833
+ end
1834
+
1835
+ def actuate
1836
+ self.node['actuate']
1837
+ end
1838
+
1839
+ # Set when the stream should be retrieved.
1840
+ # Possible values are: onLoad, onRequest, other or none.
1841
+ # Default is onRequest. In this implementation the value of this
1842
+ # parameter doesn't effect when the stream is retrieved--
1843
+ # you must always use #retrieve.
1844
+ def actuate=(a)
1845
+ @node['actuate'] = a.to_s
1846
+ end
1847
+
1848
+ def encoding
1849
+ self.node['encoding']
1850
+ end
1851
+
1852
+ # Set the encoding of the stream (i.e. base64).
1853
+ # Default is none.
1854
+ def encoding=(e)
1855
+ @node['encoding'] = e.to_s
1856
+ end
1857
+
1858
+ # Retrieve when the data in the stream expires.
1859
+ # Returns a DateTime object.
1860
+ def expires
1861
+ self.node['expires'] ? DateTime.parse(self.node['expires']) : nil
1862
+ end
1863
+
1864
+ # Set when the data in the stream expires.
1865
+ def expires=(e)
1866
+ @node['expires'] = e.to_s
1867
+ end
1868
+
1869
+ def rights
1870
+ self.node['rights']
1871
+ end
1872
+
1873
+ # Set any authentication information necessary to access
1874
+ # the remote resource (i.e. a password to an encrypted document).
1875
+ # The current implementation ignores this value when retrieving
1876
+ # the stream.
1877
+ def rights=(r)
1878
+ @node['rights'] = r.to_s
1879
+ end
1880
+
1881
+ # If the stream is text-based, it can be directly embedded
1882
+ # within the document, and can be retrieved with this method.
1883
+ def text
1884
+ self.node['content']
1885
+ end
1886
+
1887
+ # If the stream is text-based it can be directly embedded with
1888
+ # this method.
1889
+ # stream.text = 'AAAAAj/yVZiDGSSUwFZ6ypR4yGkADwAcQV0euAAIAAJBmMzNwZWZmkGle4tBR3jVQT9ocwAA'
1890
+ def text=(txt)
1891
+ @node['content'] = txt.to_s
1892
+ end
1893
+
1894
+ # Retrieve the document specified by #href.
1895
+ # Returns a File object, of if the document is
1896
+ # directly embedded in the stream a StringIO object.
1897
+ def retrieve
1898
+ shref = self.href
1899
+
1900
+ if shref
1901
+ shref.scheme == 'file' ? File.open(shref.path) : open(shref.to_s)
1902
+ else
1903
+ StringIO.new(self.text)
1904
+ end
1905
+ end
1906
+
1907
+ protected
1908
+
1909
+ def methods_to_test_for_equality
1910
+ [:type, :href, :actuate, :encoding, :expires, :rights, :text]
1911
+ end
1912
+ end
1913
+
1914
+ # Tabular data represented as a FITS[http://archive.stsci.edu/fits/fits_standard/] file.
1915
+ class Fits < VORuby::VOTable::Base
1916
+ ELEMENT_NAME = 'FITS'
1917
+
1918
+ # Create a new FITS data stream.
1919
+ # fits = Fits.new(
1920
+ # :extnum => 2,
1921
+ # :stream => Stream.new(:href => http://fits.gsfc.nasa.gov/nrao_data/samples/image/swp05569slg.fits')
1922
+ # )
1923
+ def initialize(defn=nil)
1924
+ super(defn)
1925
+ end
1926
+
1927
+ # Retrieve the FITS extension number.
1928
+ # Returns an integer.
1929
+ def extnum
1930
+ self.node['extnum'] ? self.node['extnum'].to_i : nil
1931
+ end
1932
+
1933
+ # Set the FITS extension number.
1934
+ def extnum=(e)
1935
+ @node['extnum'] = e.to_s
1936
+ end
1937
+
1938
+ # Retrieve the stream (Stream) associated with the FITS file.
1939
+ def stream
1940
+ get_element(Stream)
1941
+ end
1942
+
1943
+ # Set the stream (Stream) associated with the FITS file.
1944
+ # fits.stream = Stream.new(:href => 'http://whatever/my_fits.fits')
1945
+ def stream=(s)
1946
+ set_element(Stream, s)
1947
+ end
1948
+
1949
+ # Retrieves the FITS file locally and returns it.
1950
+ # If rfits[http://rubyforge.org/projects/rfits/] is present
1951
+ # a RFits::File object is returned (or a RFits::HDU subclass if #extnum is specified).
1952
+ # If rfits is _not_ present a File object is returned instead.
1953
+ def to_rfits
1954
+ io = self.stream.retrieve
1955
+
1956
+ io_obj = if io.is_a?(StringIO)
1957
+ tmp = Tempfile.new('fits')
1958
+ tmp.write(io.read)
1959
+ tmp
1960
+ else
1961
+ io
1962
+ end
1963
+
1964
+ # RFits isn't absolutely required, but it's nice to have.
1965
+ return io_obj if !VORuby.rfits?
1966
+
1967
+ rfits = RFits::File.new(io_obj.path)
1968
+ self.extnum ? rfits[self.extnum - 1] : rfits
1969
+ end
1970
+
1971
+ protected
1972
+
1973
+ def methods_to_test_for_equality
1974
+ [:extnum, :stream]
1975
+ end
1976
+ end
1977
+
1978
+ # A row of data in a TableData.
1979
+ class Tr < VORuby::VOTable::Base
1980
+ ELEMENT_NAME = 'TR'
1981
+
1982
+ # Create a new row of data.
1983
+ # tr = Tr.new(:tds => [Td.new()])
1984
+ def initialize(defn=nil)
1985
+ super(defn)
1986
+ end
1987
+
1988
+ # Retrieve the table data elements in the row.
1989
+ # Returns a HomogeneousNodeList.
1990
+ def tds
1991
+ HomogeneousNodeList.new(self.node, xpath_for(Td), Td)
1992
+ end
1993
+
1994
+ # Set the data elements of the row.
1995
+ # tr.tds = [Td.new(), ...]
1996
+ def tds=(columns)
1997
+ self.tds.replace(columns)
1998
+ end
1999
+
2000
+ # Convert a table row to HTML.
2001
+ # tr = Tr.new(:tds => [Td.new(:text => 'hello'), Td.new(:text => 'world')])
2002
+ # puts tr.to_html # =>
2003
+ # <tr>
2004
+ # <td>hello</td>
2005
+ # <td>world</td>
2006
+ # </tr>
2007
+ def to_html
2008
+ builder = Builder::XmlMarkup.new(:indent => 2, :margin => 4)
2009
+
2010
+ builder.tr { |tr|
2011
+ self.tds.each do |column|
2012
+ tr << column.to_html
2013
+ end
2014
+ }
2015
+ end
2016
+
2017
+ protected
2018
+
2019
+ def methods_to_test_for_equality; [:tds] end
2020
+ end
2021
+
2022
+ # A data element in a table row.
2023
+ class Td < VORuby::VOTable::Base
2024
+ include Castable
2025
+
2026
+ ELEMENT_NAME = 'TD'
2027
+
2028
+ # Create a new data element.
2029
+ # td = Td.new(:text => '123.2')
2030
+ def initialize(defn=nil)
2031
+ super(defn)
2032
+ end
2033
+
2034
+ def encoding
2035
+ self.node['encoding']
2036
+ end
2037
+
2038
+ def encoding=(e)
2039
+ @node['encoding'] = e.to_s
2040
+ end
2041
+
2042
+ # Retrieve the value of the data element as text.
2043
+ def text
2044
+ self.node.content
2045
+ end
2046
+
2047
+ # Set the value of the data element as text.
2048
+ def text=(txt)
2049
+ @node.content = txt.to_s
2050
+ end
2051
+
2052
+ # Retrieve the value of the data element as an appropriate
2053
+ # object (or list of objects), according to the datatype and arraysize of the
2054
+ # Field corresponding to this column. See Castable#as_obj
2055
+ # for more details.
2056
+ def value
2057
+ cfield = self.field
2058
+ as_obj(self.text, cfield.datatype, cfield.arraysize)
2059
+ end
2060
+
2061
+ # Set the value of the data element.
2062
+ # An attempt is made to convert native ruby types using the datatype and
2063
+ # arraysize parameters of the associated Field.
2064
+ def value=(v)
2065
+ cfield = self.field
2066
+ self.text = as_string(v, cfield.datatype, cfield.arraysize)
2067
+ end
2068
+
2069
+ # Retrieve the Field associated with this column.
2070
+ def field
2071
+ node_path = self.node.path
2072
+
2073
+ # use the xpath to determine the position
2074
+ pos = (node_path =~ /TD\[\d+\]$/) ?
2075
+ node_path.split('/').last.match(/TD\[(\d+)\]$/)[1] :
2076
+ '1'
2077
+
2078
+ field_node = self.node.find_first("../../../../*[local-name()='FIELD'][#{pos}]")
2079
+ field_node ? Field.new(field_node) : raise("Unable to associate a FIELD with this TD")
2080
+ end
2081
+
2082
+ # Convert a column to HTML.
2083
+ # td = Td.new(:text => 'hello')
2084
+ # puts td.to_html # => <td>hello</td>
2085
+ def to_html
2086
+ builder = Builder::XmlMarkup.new(:indent => 2, :margin => 5)
2087
+
2088
+ builder.td(self.text)
2089
+ end
2090
+
2091
+ protected
2092
+
2093
+ def methods_to_test_for_equality
2094
+ [:encoding, :text]
2095
+ end
2096
+ end
2097
+
2098
+ end
2099
+ end
2100
+ end