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