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.
- data/Rakefile.rb +107 -224
- data/lib/misc.rb +1 -0
- data/lib/misc/misc.rb +60 -0
- data/lib/misc/propertyfile.rb +31 -0
- data/lib/symphony.rb +1 -0
- data/lib/symphony/symphony.rb +247 -0
- data/lib/voruby.rb +186 -0
- data/lib/voruby/active_votable/active_votable.rb +468 -347
- data/lib/voruby/adql/1.0/adql.rb +2418 -0
- data/lib/voruby/adql/support.rb +2 -0
- data/lib/voruby/misc.rb +351 -0
- data/lib/voruby/misc/connection_monitor.rb +97 -0
- data/lib/voruby/misc/libxml_ext.rb +121 -0
- data/lib/voruby/misc/rexml_ext.rb +223 -0
- data/lib/voruby/resolver/resolver.rb +12 -0
- data/lib/voruby/resolver/sesame.rb +299 -0
- data/lib/voruby/sky_query/sky_query.rb +192 -0
- data/lib/voruby/stc/1.10/coords.rb +2272 -0
- data/lib/voruby/stc/1.10/region.rb +892 -0
- data/lib/voruby/stc/1.10/stc.rb +3271 -0
- data/lib/voruby/stc/1.30/stc.rb +8666 -0
- data/lib/voruby/stc/support.rb +2 -0
- data/lib/voruby/ucd/ucd.rb +173 -0
- data/lib/voruby/voevent/1.1/voevent.rb +1124 -0
- data/lib/voruby/voevent/support.rb +5 -0
- data/lib/voruby/votable/1.0/votable.rb +1807 -0
- data/lib/voruby/votable/1.1/votable.rb +2100 -0
- data/lib/voruby/votable/votable.rb +305 -0
- data/lib/voruby/wesix/wesix.rb +491 -0
- data/lib/voruby/xlink/1.2/xlink.rb +21 -0
- data/test/voruby/active_votable/complex.vot +60 -0
- data/test/voruby/active_votable/error.vot +6 -0
- data/test/voruby/active_votable/large.vot +130040 -0
- data/test/voruby/active_votable/simple1.vot +38 -0
- data/test/voruby/active_votable/simple2.vot +38 -0
- data/test/voruby/active_votable/test.rb +193 -0
- data/test/voruby/adql/1.0/adql-alias.sql +1 -0
- data/test/voruby/adql/1.0/adql-alias.xml +26 -0
- data/test/voruby/adql/1.0/adql-avg.sql +1 -0
- data/test/voruby/adql/1.0/adql-avg.xml +31 -0
- data/test/voruby/adql/1.0/adql-circle.sql +1 -0
- data/test/voruby/adql/1.0/adql-circle.xml +46 -0
- data/test/voruby/adql/1.0/adql-expr.sql +1 -0
- data/test/voruby/adql/1.0/adql-expr.xml +34 -0
- data/test/voruby/adql/1.0/adql-function.sql +1 -0
- data/test/voruby/adql/1.0/adql-function.xml +41 -0
- data/test/voruby/adql/1.0/adql-group.sql +1 -0
- data/test/voruby/adql/1.0/adql-group.xml +51 -0
- data/test/voruby/adql/1.0/adql-having.sql +1 -0
- data/test/voruby/adql/1.0/adql-having.xml +25 -0
- data/test/voruby/adql/1.0/adql-like.sql +1 -0
- data/test/voruby/adql/1.0/adql-like.xml +17 -0
- data/test/voruby/adql/1.0/adql-order.sql +1 -0
- data/test/voruby/adql/1.0/adql-order.xml +37 -0
- data/test/voruby/adql/1.0/adql-simple.sql +1 -0
- data/test/voruby/adql/1.0/adql-simple.xml +12 -0
- data/test/voruby/adql/1.0/adql-top.sql +1 -0
- data/test/voruby/adql/1.0/adql-top.xml +33 -0
- data/test/voruby/adql/1.0/test.rb +2220 -0
- data/test/voruby/misc/test.rb +32 -0
- data/test/voruby/resolver/sesame/test.rb +56 -0
- data/test/voruby/sky_query/test.rb +107 -0
- data/test/voruby/stc/1.10/coords_test.rb +3704 -0
- data/test/voruby/stc/1.10/region_test.rb +993 -0
- data/test/voruby/stc/1.10/stc-catalog-entry-location.xml +112 -0
- data/test/voruby/stc/1.10/stc-obs-data-location.xml +126 -0
- data/test/voruby/stc/1.10/stc-region-circle.xml +5 -0
- data/test/voruby/stc/1.10/stc-region-convex.xml +11 -0
- data/test/voruby/stc/1.10/stc-region-convexhull.xml +5 -0
- data/test/voruby/stc/1.10/stc-region-ellipse.xml +7 -0
- data/test/voruby/stc/1.10/stc-region-intersection.xml +25 -0
- data/test/voruby/stc/1.10/stc-region-negation.xml +7 -0
- data/test/voruby/stc/1.10/stc-region-polygon.xml +13 -0
- data/test/voruby/stc/1.10/stc-region-sector.xml +6 -0
- data/test/voruby/stc/1.10/stc-region-union.xml +25 -0
- data/test/voruby/stc/1.10/stc-resource-profile.xml +60 -0
- data/test/voruby/stc/1.10/stc-search-location.xml +54 -0
- data/test/voruby/stc/1.10/stc_test.rb +4626 -0
- data/test/voruby/stc/1.30/stc-catalog-entry-location.xml +210 -0
- data/test/voruby/stc/1.30/stc-obs-data-location-arecibo.xml +353 -0
- data/test/voruby/stc/1.30/stc-obs-data-location-fits.xml +250 -0
- data/test/voruby/stc/1.30/stc-obs-data-location-xlink.xml +63 -0
- data/test/voruby/stc/1.30/stc-obs-data-location.xml +216 -0
- data/test/voruby/stc/1.30/stc-resource-profile-unusual-ref-pos.xml +39 -0
- data/test/voruby/stc/1.30/stc-resource-profile.xml +129 -0
- data/test/voruby/stc/1.30/stc-search-location-arecibo.xml +86 -0
- data/test/voruby/stc/1.30/stc-search-location.xml +101 -0
- data/test/voruby/stc/1.30/test.rb +6274 -0
- data/test/voruby/ucd/test.rb +48 -0
- data/test/voruby/voevent/1.1/test.rb +812 -0
- data/test/{voevent/voevent_v1_1.xml → voruby/voevent/1.1/voevent.xml} +2 -2
- data/test/voruby/voregistry/0.3/test.rb +137 -0
- data/test/voruby/votable/1.0/test.rb +714 -0
- data/test/voruby/votable/1.0/votable.basic.xml +660 -0
- data/test/voruby/votable/1.0/votable.html +86 -0
- data/test/voruby/votable/1.0/votable.ns.xml +56 -0
- data/test/voruby/votable/1.1/test.rb +785 -0
- data/test/voruby/votable/1.1/votable.basic.xml +38 -0
- data/test/voruby/votable/1.1/votable.html +86 -0
- data/test/voruby/votable/1.1/votable.ns.xml +56 -0
- data/test/voruby/votable/test.rb +15 -0
- data/test/voruby/wesix/test.rb +268 -0
- data/test/voruby/wesix/testr.fits +28 -0
- metadata +234 -247
- data/REQUIREMENTS +0 -6
- data/lib/voruby/active_votable/loader.rb +0 -5
- data/lib/voruby/adql/adql.rb +0 -2787
- data/lib/voruby/adql/ext.rb +0 -14
- data/lib/voruby/adql/loader.rb +0 -6
- data/lib/voruby/adql/operations.rb +0 -54
- data/lib/voruby/adql/parser.rb +0 -160
- data/lib/voruby/adql/transforms.rb +0 -573
- data/lib/voruby/ext.rb +0 -17
- data/lib/voruby/loader.rb +0 -4
- data/lib/voruby/misc/propertyfile.rb +0 -36
- data/lib/voruby/plastic/applications.rb +0 -174
- data/lib/voruby/plastic/constants.rb +0 -30
- data/lib/voruby/plastic/loader.rb +0 -10
- data/lib/voruby/plastic/plastic.rb +0 -1
- data/lib/voruby/resources/conesearch/conesearch.rb +0 -9
- data/lib/voruby/resources/conesearch/conesearch_v0_2.rb +0 -55
- data/lib/voruby/resources/conesearch/conesearch_v0_3.rb +0 -50
- data/lib/voruby/resources/conesearch/conesearch_v1_0.rb +0 -72
- data/lib/voruby/resources/conesearch/loader.rb +0 -4
- data/lib/voruby/resources/loader.rb +0 -50
- data/lib/voruby/resources/nodes.rb +0 -190
- data/lib/voruby/resources/openskynode/loader.rb +0 -4
- data/lib/voruby/resources/openskynode/openskynode.rb +0 -9
- data/lib/voruby/resources/openskynode/openskynode_v0_1.rb +0 -54
- data/lib/voruby/resources/sia/loader.rb +0 -5
- data/lib/voruby/resources/sia/sia.rb +0 -9
- data/lib/voruby/resources/sia/sia_v0_6.rb +0 -90
- data/lib/voruby/resources/sia/sia_v0_7.rb +0 -89
- data/lib/voruby/resources/sia/sia_v1_0.rb +0 -122
- data/lib/voruby/resources/stsci.rb +0 -59
- data/lib/voruby/resources/vodataservice/coverage_v0_2.rb +0 -195
- data/lib/voruby/resources/vodataservice/coverage_v0_3.rb +0 -158
- data/lib/voruby/resources/vodataservice/loader.rb +0 -5
- data/lib/voruby/resources/vodataservice/vodataservice.rb +0 -9
- data/lib/voruby/resources/vodataservice/vodataservice_v0_4.rb +0 -189
- data/lib/voruby/resources/vodataservice/vodataservice_v0_5.rb +0 -163
- data/lib/voruby/resources/vodataservice/vodataservice_v1_0.rb +0 -221
- data/lib/voruby/resources/voregistry/loader.rb +0 -4
- data/lib/voruby/resources/voregistry/voregistry.rb +0 -9
- data/lib/voruby/resources/voregistry/voregistry_v0_2.rb +0 -40
- data/lib/voruby/resources/voregistry/voregistry_v0_3.rb +0 -30
- data/lib/voruby/resources/voregistry/voregistry_v1_0.rb +0 -86
- data/lib/voruby/resources/voresource/loader.rb +0 -17
- data/lib/voruby/resources/voresource/voresource.rb +0 -9
- data/lib/voruby/resources/voresource/voresource_v0_10.rb +0 -327
- data/lib/voruby/resources/voresource/voresource_v0_9.rb +0 -405
- data/lib/voruby/resources/voresource/voresource_v1_0.rb +0 -230
- data/lib/voruby/services/ext.rb +0 -11
- data/lib/voruby/services/gestalt/footprint.rb +0 -95
- data/lib/voruby/services/gestalt/wcs_fixer.rb +0 -105
- data/lib/voruby/services/gestalt/wesix.rb +0 -155
- data/lib/voruby/services/loader.rb +0 -7
- data/lib/voruby/services/registry/registry.rb +0 -53
- data/lib/voruby/services/resolver/resolver.rb +0 -35
- data/lib/voruby/services/schema/schema.rb +0 -644
- data/lib/voruby/sesame/loader.rb +0 -6
- data/lib/voruby/sesame/sesame_v1_0.rb +0 -64
- data/lib/voruby/simple/loader.rb +0 -6
- data/lib/voruby/simple/parameters.rb +0 -196
- data/lib/voruby/simple/sap.rb +0 -446
- data/lib/voruby/spacetime/loader.rb +0 -3
- data/lib/voruby/spacetime/spacetime.rb +0 -607
- data/lib/voruby/stc/coords_v1_20.rb +0 -900
- data/lib/voruby/stc/loader.rb +0 -55
- data/lib/voruby/stc/region_v1_20.rb +0 -274
- data/lib/voruby/stc/stc_v1_20.rb +0 -1196
- data/lib/voruby/util.rb +0 -27
- data/lib/voruby/voevent/loader.rb +0 -7
- data/lib/voruby/voevent/voevent_v1_0.rb +0 -213
- data/lib/voruby/voevent/voevent_v1_1.rb +0 -196
- data/lib/voruby/votables/chandra.rb +0 -373
- data/lib/voruby/votables/data.rb +0 -179
- data/lib/voruby/votables/galex.rb +0 -377
- data/lib/voruby/votables/int.rb +0 -354
- data/lib/voruby/votables/libxml_parser.rb +0 -411
- data/lib/voruby/votables/libxml_votable.rb +0 -67
- data/lib/voruby/votables/loader.rb +0 -10
- data/lib/voruby/votables/meta.rb +0 -763
- data/lib/voruby/votables/misc.rb +0 -51
- data/lib/voruby/votables/nsa.rb +0 -410
- data/lib/voruby/votables/rexml_parser.rb +0 -408
- data/lib/voruby/votables/rexml_votable.rb +0 -67
- data/lib/voruby/votables/sdss.rb +0 -356
- data/lib/voruby/votables/transforms.rb +0 -388
- data/lib/voruby/votables/tree.rb +0 -45
- data/lib/voruby/votables/types.rb +0 -391
- data/lib/voruby/votables/votable.rb +0 -687
- data/test/active_votable/database.yml +0 -6
- data/test/active_votable/test.vot +0 -168492
- data/test/active_votable/unittest.rb +0 -41
- data/test/adql/test1.adql +0 -49
- data/test/adql/test2.adql +0 -51
- data/test/adql/test3.adql +0 -81
- data/test/adql/test4.adql +0 -53
- data/test/adql/test5.adql +0 -55
- data/test/adql/test6.adql +0 -18
- data/test/adql/test7.adql +0 -48
- data/test/adql/unittest.rb +0 -1672
- data/test/plastic/test.rb +0 -44
- data/test/plastic/test.vot +0 -5385
- data/test/plastic/unittest.rb +0 -66
- data/test/resources/conesearch/conesearch_v0_3.xml +0 -31
- data/test/resources/conesearch/conesearch_v1_0.xml +0 -86
- data/test/resources/conesearch/unittest_v0_3.rb +0 -22
- data/test/resources/conesearch/unittest_v1_0.rb +0 -24
- data/test/resources/openskynode/open_sky_node_v0_1.xml +0 -32
- data/test/resources/openskynode/unittest_v0_1.rb +0 -31
- data/test/resources/sia/simple_image_access_v0_7.xml +0 -36
- data/test/resources/sia/simple_image_access_v1_0.xml +0 -122
- data/test/resources/sia/unittest_v0_7.rb +0 -24
- data/test/resources/sia/unittest_v1_0.rb +0 -29
- data/test/resources/stsci.xml +0 -336
- data/test/resources/unittest_stsci.rb +0 -25
- data/test/resources/vodataservice/catalog_service_resource_v1_0.xml +0 -128
- data/test/resources/vodataservice/data_collection_resource_v0_5.xml +0 -54
- data/test/resources/vodataservice/data_collection_resource_v1_0.xml +0 -117
- data/test/resources/vodataservice/data_service_resource_v1_0.xml +0 -115
- data/test/resources/vodataservice/sky_service_resource_v0_10.xml +0 -45
- data/test/resources/vodataservice/table_service_resource_v1_0.xml +0 -122
- data/test/resources/vodataservice/tabular_sky_service_resource_v0_10.xml +0 -60
- data/test/resources/vodataservice/unittest_v0_5.rb +0 -126
- data/test/resources/vodataservice/unittest_v1_0.rb +0 -151
- data/test/resources/voregistry/authority_resource_v0_3.xml +0 -20
- data/test/resources/voregistry/authority_resource_v1_0.xml +0 -82
- data/test/resources/voregistry/registry_service_v0_3.xml +0 -20
- data/test/resources/voregistry/registry_service_v1_0.xml +0 -107
- data/test/resources/voregistry/unittest_v0_3.rb +0 -31
- data/test/resources/voregistry/unittest_v1_0.rb +0 -34
- data/test/resources/voresource/organisation_resource_v1_0.xml +0 -90
- data/test/resources/voresource/resource_organisation_v0_10.xml +0 -22
- data/test/resources/voresource/resource_service_v0_10.xml +0 -19
- data/test/resources/voresource/resource_v0_10.xml +0 -19
- data/test/resources/voresource/resource_v1_0.xml +0 -79
- data/test/resources/voresource/service_resource_v1_0.xml +0 -91
- data/test/resources/voresource/unittest_v0_10.rb +0 -61
- data/test/resources/voresource/unittest_v0_9.rb +0 -4
- data/test/resources/voresource/unittest_v1_0.rb +0 -190
- data/test/services/gestalt/unittest.rb +0 -74
- data/test/services/registry/unittest.rb +0 -34
- data/test/services/resolver/unittest.rb +0 -38
- data/test/simple/unittest.rb +0 -46
- data/test/spacetime/unittest.rb +0 -39
- data/test/stc/catalog_entry_location_v1_20.xml +0 -112
- data/test/stc/obs_data_location_v1_20.xml +0 -108
- data/test/stc/search_location_v1_20.xml +0 -54
- data/test/stc/stc_resource_profile_v1_20.xml +0 -60
- data/test/stc/unittest_v1_20.rb +0 -620
- data/test/voevent/unittest_v1_0.rb +0 -79
- data/test/voevent/unittest_v1_1.rb +0 -70
- data/test/voevent/voevent_v1_0.xml +0 -96
- data/test/votables/test.vot +0 -366
- data/test/votables/unittest.rb +0 -54
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'soap/rpc/driver'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module VORuby
|
5
|
+
# Unified Content Descriptors[http://www.ivoa.net/Documents/latest/UCD.html] or UCDs constitute a controlled vocabulary
|
6
|
+
# used throughout the VO. This class provides some useful methods for dealing with them.
|
7
|
+
class UCD
|
8
|
+
attr_accessor :check_availability
|
9
|
+
|
10
|
+
# Create a new UCD resolver.
|
11
|
+
# <tt>options</tt> is a hash with the following keys:
|
12
|
+
#
|
13
|
+
# [<tt>:end_point</tt>] the UCD SOAP endpoint to use (default: http://cdsws.u-strasbg.fr/axis/services/UCD)
|
14
|
+
# [<tt>:check_availability</tt>] whether to try to determine if the sesame service is available or not before each name resolution (default: false)
|
15
|
+
#
|
16
|
+
# ucd = UCD.new(
|
17
|
+
# :end_point => 'ttp://vizier.hia.nrc.ca:8080/axis/services/UCD' # maybe we're in Canada...
|
18
|
+
# :check_availability => true # and we want to always check the availability of the service
|
19
|
+
# )
|
20
|
+
def initialize(options={})
|
21
|
+
self.end_point = options[:end_point] || 'http://cdsws.u-strasbg.fr/axis/services/UCD'
|
22
|
+
self.check_availability = options[:check_availability] || false
|
23
|
+
end
|
24
|
+
|
25
|
+
# The "end-point" or location of the UCD resolver's webservice.
|
26
|
+
def end_point
|
27
|
+
@end_point
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set the end-point or location of the UCD resolver's webservice.
|
31
|
+
# ucd.end_point = 'http://vizier.hia.nrc.ca:8080/axis/services/UCD'
|
32
|
+
def end_point=(epoint)
|
33
|
+
@end_point = epoint
|
34
|
+
|
35
|
+
@resolver = SOAP::RPC::Driver.new(@end_point)
|
36
|
+
@resolver.add_rpc_method('translate', 'ucd')
|
37
|
+
@resolver.add_rpc_method('assign', 'descr')
|
38
|
+
@resolver.add_rpc_method('explain', 'ucd')
|
39
|
+
@resolver.add_rpc_method('resolveUCD', 'ucd')
|
40
|
+
@resolver.add_rpc_method('validate', 'ucd')
|
41
|
+
@resolver.add_rpc_method('upgrade','ucd')
|
42
|
+
@resolver.add_rpc_method('getAvailability')
|
43
|
+
end
|
44
|
+
|
45
|
+
# Translate an old-style UCD1 into it's newer UCD1+ form.
|
46
|
+
# Returns <tt>nil</tt> if the UCD is untranslatable.
|
47
|
+
#
|
48
|
+
# ucd.translate('POS_EQ_RA_MAIN') # => 'pos.eq.ra;meta.main'
|
49
|
+
def translate(ucd)
|
50
|
+
raise "UCD resolver at #{self.end_point} is not currently available" if self.check_availability and !self.available?
|
51
|
+
|
52
|
+
ucd_plus = @resolver.translate(ucd).strip
|
53
|
+
ucd_plus.match('Could not translate') ? nil : ucd_plus
|
54
|
+
end
|
55
|
+
|
56
|
+
# Convenience class method for #translate.
|
57
|
+
def self.translate(ucd, options={})
|
58
|
+
self.new(options).translate(ucd)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Given a text description of a parameter (i.e. V magnitude), find
|
62
|
+
# a likely corresponding UCD1+. Returns <tt>nil</tt> if no UCD is found.
|
63
|
+
#
|
64
|
+
# ucd.assign('V magnitude') # => 'phot.mag;em.opt.V'
|
65
|
+
def assign(descr)
|
66
|
+
raise "UCD resolver at #{self.end_point} is not currently available" if self.check_availability and !self.available?
|
67
|
+
|
68
|
+
ucd_plus = @resolver.assign(descr).strip
|
69
|
+
ucd_plus.match('Could not find') ? nil : ucd_plus
|
70
|
+
end
|
71
|
+
|
72
|
+
# Convenience class method for #assign.
|
73
|
+
def self.assign(descr, options={})
|
74
|
+
self.new(options).assign(descr)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Given a UCD, discover a human-readable description.
|
78
|
+
# <tt>version</tt> may be '1+' (the default) for a UCD1+ or
|
79
|
+
# '1' for an old-style UCD.
|
80
|
+
# Returns <tt>nil</tt> if the UCD is not recognized.
|
81
|
+
#
|
82
|
+
# ucd.explain('ivoa:phot.mag;em.opt.B') # => 'Photometric magnitude / Optical band between 400 and 500 nm'
|
83
|
+
# ucd.explain('PHOT_JHN_V', '1') # => 'Johnson magnitude V (JHN)'
|
84
|
+
def explain(ucd, version='1+')
|
85
|
+
version ||= '1+'
|
86
|
+
raise "UCD resolver at #{self.end_point} is not currently available" if self.check_availability and !self.available?
|
87
|
+
|
88
|
+
descr = case version
|
89
|
+
when '1'
|
90
|
+
@resolver.resolveUCD(ucd)
|
91
|
+
else
|
92
|
+
@resolver.explain(ucd)
|
93
|
+
end
|
94
|
+
|
95
|
+
(descr.match('Non-standard UCD') or descr.match('Invalid UCD')) ? nil : descr.strip
|
96
|
+
end
|
97
|
+
|
98
|
+
# Convenience class method for #explain.
|
99
|
+
def self.explain(ucd, version='1+', options={})
|
100
|
+
self.new(options).explain(ucd, version)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Validate a specifed UCD1+. Returns an object that responds
|
104
|
+
# to a #code method and a human-readable list of of error strings.
|
105
|
+
# A <tt>code</tt> of 0 implies the UCD is valid. Possible combinations
|
106
|
+
# arise from bitwise-OR'ing the following:
|
107
|
+
#
|
108
|
+
# * 1: warning indicating use of non-standard namespace (not ivoa:)
|
109
|
+
# * 2: use of deprecated word
|
110
|
+
# * 4: use of non-existing word
|
111
|
+
# * 8: syntax error (extra space or unallowed character)
|
112
|
+
#
|
113
|
+
# result = ucd.validate('ivob:phot.mag;em.opt.Z')
|
114
|
+
# puts result.code # => 5
|
115
|
+
# puts result.errors => ["use of non-standard namespace 'ivob'", "invalid UCD word 'em.opt.Z'"]
|
116
|
+
def validate(ucd)
|
117
|
+
raise "UCD resolver at #{self.end_point} is not currently available" if self.check_availability and !self.available?
|
118
|
+
|
119
|
+
error = @resolver.validate(ucd).strip
|
120
|
+
parts = error.split(/\s*\*\*\*\*\s*/)
|
121
|
+
|
122
|
+
OpenStruct.new(
|
123
|
+
:code => parts.first.to_i,
|
124
|
+
:errors => parts[1..-1]
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Convenience class method for #validate.
|
129
|
+
def self.validate(ucd, options={})
|
130
|
+
self.new(options).validate(ucd)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns true or false depending on whether a UCD1+ is
|
134
|
+
# valid. This is the same checking the <tt>code</tt> on the object
|
135
|
+
# that #validate returns.
|
136
|
+
#
|
137
|
+
# ucd.valid?('ivob:phot.mag;em.opt.Z') # => false
|
138
|
+
# ucd.valid?('ivoa:phot.mag;em.opt.B') # => true
|
139
|
+
def valid?(ucd)
|
140
|
+
self.validate(ucd).code == 0 ? true : false
|
141
|
+
end
|
142
|
+
|
143
|
+
# Convenience class method for #valid?.
|
144
|
+
def self.valid?(ucd, options={})
|
145
|
+
self.new(options).valid?(ucd)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Find a valid UCD1+ corresponding to a deprecated word.
|
149
|
+
#
|
150
|
+
# ucd.upgrade('pos.gal.lat') # => 'pos.galactic.lat'
|
151
|
+
def upgrade(ucd)
|
152
|
+
raise "UCD resolver at #{self.end_point} is not currently available" if self.check_availability and !self.available?
|
153
|
+
@resolver.upgrade(ucd).strip
|
154
|
+
end
|
155
|
+
|
156
|
+
# Convenience class method for #upgrade.
|
157
|
+
def self.upgrade(ucd, options={})
|
158
|
+
self.new(options).upgrade(ucd)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Checks to see whether the UCD resolver is available.
|
162
|
+
# At this point it's assumed the service is present at
|
163
|
+
# the location specified by #end_point. This just checks
|
164
|
+
# to see whether sesame reports itself as available or not.
|
165
|
+
def available?
|
166
|
+
# We don't use an XML parser here because (as of 2007-01-04)
|
167
|
+
# the validTo tag isn't closed properly, rendering the XML
|
168
|
+
# malformed.
|
169
|
+
result = @resolver.getAvailability
|
170
|
+
result.match(/<available>\s*(.*)\s*<\/available>/)[1] == 'true'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,1124 @@
|
|
1
|
+
require 'voruby/voevent/support'
|
2
|
+
require 'voruby/stc/1.30/stc'
|
3
|
+
include VORuby::STC::V1_30
|
4
|
+
|
5
|
+
module VORuby
|
6
|
+
module VOEvent
|
7
|
+
module V1_1
|
8
|
+
include XMLUtilities
|
9
|
+
|
10
|
+
class Base
|
11
|
+
include SerializableToXml
|
12
|
+
end
|
13
|
+
|
14
|
+
# External content.
|
15
|
+
class Reference < Base
|
16
|
+
attr_accessor :type, :name
|
17
|
+
attr_reader :uri
|
18
|
+
|
19
|
+
def initialize(uri, type='url', name=nil)
|
20
|
+
self.uri = uri
|
21
|
+
self.type = type || 'url'
|
22
|
+
self.name = name
|
23
|
+
end
|
24
|
+
|
25
|
+
def uri=(u)
|
26
|
+
raise_argument_required_error('URI') if !u
|
27
|
+
@uri = u.is_a?(URI) ? u : URI.parse(u.to_s)
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(r)
|
31
|
+
self.uri == r.uri and
|
32
|
+
self.type == r.type and
|
33
|
+
self.name == r.name
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_xml(name=nil)
|
37
|
+
el = element(name)
|
38
|
+
|
39
|
+
el.attributes["#{obj_ns.prefix}:uri"] = self.uri.to_s
|
40
|
+
el.attributes["#{obj_ns.prefix}:name"] = self.name.to_s if self.name
|
41
|
+
el.attributes["#{obj_ns.prefix}:type"] = self.type.to_s if self.type
|
42
|
+
|
43
|
+
el
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.from_xml(xml)
|
47
|
+
root = element_from(xml)
|
48
|
+
|
49
|
+
name = root.attributes.get_attribute_ns(obj_ns.uri, 'name')
|
50
|
+
type = root.attributes.get_attribute_ns(obj_ns.uri, 'type')
|
51
|
+
|
52
|
+
self.new(
|
53
|
+
URI.parse(root.attributes.get_attribute_ns(obj_ns.uri, 'uri').value),
|
54
|
+
type ? type.value : nil,
|
55
|
+
name ? name.value : nil
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Human readable text.
|
61
|
+
class Description < Base
|
62
|
+
attr_accessor :format
|
63
|
+
attr_reader :value
|
64
|
+
|
65
|
+
def initialize(value, format='text/plain')
|
66
|
+
self.value = value
|
67
|
+
self.format = format || 'text/plain'
|
68
|
+
end
|
69
|
+
|
70
|
+
def value=(v)
|
71
|
+
raise_argument_required_error('description value') if !v
|
72
|
+
@value = v.to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
def ==(d)
|
76
|
+
self.value == d.value and
|
77
|
+
self.format == d.format
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_xml(name=nil)
|
81
|
+
el = element(name)
|
82
|
+
|
83
|
+
el.text = self.value.to_s
|
84
|
+
el.attributes["#{obj_ns.prefix}:format"] = self.format.to_s if self.format
|
85
|
+
|
86
|
+
el
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.from_xml(xml)
|
90
|
+
root = element_from(xml)
|
91
|
+
|
92
|
+
format = root.attributes.get_attribute_ns(obj_ns.uri, 'format')
|
93
|
+
|
94
|
+
self.new(
|
95
|
+
root.texts.join('').strip,
|
96
|
+
format ? format.value : nil
|
97
|
+
)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class Cite < Enumeration
|
102
|
+
def self.choices; ['followup', 'supersedes', 'retraction'] end
|
103
|
+
end
|
104
|
+
|
105
|
+
class EventIVORN < Base
|
106
|
+
attr_reader :uri, :cite
|
107
|
+
|
108
|
+
def initialize(uri, cite)
|
109
|
+
self.uri = uri
|
110
|
+
self.cite = cite
|
111
|
+
end
|
112
|
+
|
113
|
+
def uri=(u)
|
114
|
+
raise_argument_required_error('URI') if !u
|
115
|
+
@uri = u.is_a?(URI) ? u : URI.parse(u.to_s)
|
116
|
+
end
|
117
|
+
|
118
|
+
def cite=(c)
|
119
|
+
raise_argument_required_error('cite') if !c
|
120
|
+
|
121
|
+
c = Cite.new(c) if c.is_a?(String)
|
122
|
+
raise_type_mismatch_error(c, Cite)
|
123
|
+
|
124
|
+
@cite = c
|
125
|
+
end
|
126
|
+
|
127
|
+
def ==(i)
|
128
|
+
self.uri == i.uri and
|
129
|
+
self.cite == i.cite
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_xml(name=nil)
|
133
|
+
el = element(name)
|
134
|
+
|
135
|
+
el.text = self.uri.to_s
|
136
|
+
el.attributes["#{obj_ns.prefix}:cite"] = self.cite.to_s
|
137
|
+
|
138
|
+
el
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.from_xml(xml)
|
142
|
+
root = element_from(xml)
|
143
|
+
|
144
|
+
self.new(
|
145
|
+
root.text,
|
146
|
+
Cite.new(root.attributes.get_attribute_ns(obj_ns.uri, 'cite').value)
|
147
|
+
)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class DescriptionList < TypedArray
|
152
|
+
def self.restricted_to; [Description] end
|
153
|
+
end
|
154
|
+
|
155
|
+
class ReferenceList < TypedArray
|
156
|
+
def self.restricted_to; [Reference] end
|
157
|
+
end
|
158
|
+
|
159
|
+
class Described < Base
|
160
|
+
attr_reader :descriptions, :references
|
161
|
+
|
162
|
+
def initialize(descriptions=nil, references=nil)
|
163
|
+
self.descriptions = descriptions
|
164
|
+
self.references = references
|
165
|
+
end
|
166
|
+
|
167
|
+
def descriptions=(ds)
|
168
|
+
if ds
|
169
|
+
ds = DescriptionList.new(ds) if ds.class == Array
|
170
|
+
raise_type_mismatch_error(ds, DescriptionList)
|
171
|
+
end
|
172
|
+
|
173
|
+
@descriptions = ds
|
174
|
+
end
|
175
|
+
|
176
|
+
def references=(rs)
|
177
|
+
if rs
|
178
|
+
rs = ReferenceList.new(rs) if rs.class == Array
|
179
|
+
raise_type_mismatch_error(rs, ReferenceList)
|
180
|
+
end
|
181
|
+
|
182
|
+
@references = rs
|
183
|
+
end
|
184
|
+
|
185
|
+
def ==(h)
|
186
|
+
self.descriptions == h.descriptions and
|
187
|
+
self.references == h.references
|
188
|
+
end
|
189
|
+
|
190
|
+
def to_xml(name=nil)
|
191
|
+
el = element(name)
|
192
|
+
|
193
|
+
self.descriptions.each{ |d| el.add_element(d.to_xml('Description')) } if self.descriptions
|
194
|
+
self.references.each{ |r| el.add_element(r.to_xml('Reference')) } if self.references
|
195
|
+
|
196
|
+
collapse_namespaces(el)
|
197
|
+
el
|
198
|
+
end
|
199
|
+
|
200
|
+
def self.described_from_xml(root)
|
201
|
+
descrs = REXML::XPath.match(root, 'x:Description', {'x' => obj_ns.uri})
|
202
|
+
descrs = nil if descrs.size == 0
|
203
|
+
|
204
|
+
refs = REXML::XPath.match(root, 'x:Reference', {'x' => obj_ns.uri})
|
205
|
+
refs = nil if refs.size == 0
|
206
|
+
|
207
|
+
[
|
208
|
+
descrs ? DescriptionList.new(descrs.collect{ |d| Description.from_xml(d) }) : nil,
|
209
|
+
refs ? ReferenceList.new(refs.collect{ |r| Reference.from_xml(r) }) : nil
|
210
|
+
]
|
211
|
+
end
|
212
|
+
|
213
|
+
def self.from_xml(xml)
|
214
|
+
root = element_from(xml)
|
215
|
+
self.new(*described_from_xml(root))
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Follow-up Observations.
|
220
|
+
class Citations < Described
|
221
|
+
class EventIVORNList < TypedArray
|
222
|
+
def self.restricted_to; [EventIVORN] end
|
223
|
+
def self.minimum_length; 1 end
|
224
|
+
end
|
225
|
+
|
226
|
+
attr_reader :event_ivorns
|
227
|
+
|
228
|
+
def initialize(ivorns, descriptions=nil, references=nil)
|
229
|
+
super(descriptions, references)
|
230
|
+
self.event_ivorns = ivorns
|
231
|
+
end
|
232
|
+
|
233
|
+
def event_ivorns=(eis)
|
234
|
+
raise_argument_required_error('event IVORNs') if !eis
|
235
|
+
|
236
|
+
eis = EventIVORNList.new(eis) if eis.class == Array
|
237
|
+
raise_type_mismatch_error(eis, EventIVORNList)
|
238
|
+
|
239
|
+
@event_ivorns = eis
|
240
|
+
end
|
241
|
+
|
242
|
+
def ==(c)
|
243
|
+
super(c) and
|
244
|
+
self.event_ivorns == c.event_ivorns
|
245
|
+
end
|
246
|
+
|
247
|
+
def to_xml(name=nil)
|
248
|
+
el = super(name)
|
249
|
+
|
250
|
+
self.event_ivorns.each{ |i| el.add_element(i.to_xml('EventIVORN')) }
|
251
|
+
|
252
|
+
collapse_namespaces(el)
|
253
|
+
el
|
254
|
+
end
|
255
|
+
|
256
|
+
def self.from_xml(xml)
|
257
|
+
root = element_from(xml)
|
258
|
+
|
259
|
+
ivorns = REXML::XPath.match(root, 'x:EventIVORN', {'x' => obj_ns.uri})
|
260
|
+
ivorns = nil if ivorns.size == 0
|
261
|
+
|
262
|
+
self.new(
|
263
|
+
ivorns ? EventIVORNList.new(ivorns.collect{ |e| EventIVORN.from_xml(e) }) : nil,
|
264
|
+
*Described.described_from_xml(root)
|
265
|
+
)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
class NameList < TypedArray
|
270
|
+
def self.restricted_to; [String] end
|
271
|
+
end
|
272
|
+
|
273
|
+
class ConceptList < TypedArray
|
274
|
+
def self.restricted_to; [String] end
|
275
|
+
end
|
276
|
+
|
277
|
+
class Inference < Described
|
278
|
+
attr_reader :names, :concepts, :probability, :relation
|
279
|
+
|
280
|
+
def initialize(names, concepts, probability=nil, relation=nil, descriptions=nil, references=nil)
|
281
|
+
super(descriptions, references)
|
282
|
+
self.names = names
|
283
|
+
self.concepts = concepts
|
284
|
+
self.probability = probability
|
285
|
+
self.relation = relation
|
286
|
+
end
|
287
|
+
|
288
|
+
def names=(ns)
|
289
|
+
if ns
|
290
|
+
ns = NameList.new(ns) if ns.class == Array
|
291
|
+
raise_type_mismatch_error(ns, NameList)
|
292
|
+
end
|
293
|
+
|
294
|
+
@names = ns
|
295
|
+
end
|
296
|
+
|
297
|
+
def concepts=(cs)
|
298
|
+
if cs
|
299
|
+
cs = ConceptList.new(cs) if cs.class == Array
|
300
|
+
raise_type_mismatch_error(cs, ConceptList)
|
301
|
+
end
|
302
|
+
|
303
|
+
@concepts = cs
|
304
|
+
end
|
305
|
+
|
306
|
+
def probability=(p)
|
307
|
+
if p
|
308
|
+
p = Float(p)
|
309
|
+
raise 'float must be between 0.0 and 1.0' if p < 0.0 or p > 1.0
|
310
|
+
end
|
311
|
+
|
312
|
+
@probability = p
|
313
|
+
end
|
314
|
+
|
315
|
+
def relation=(r)
|
316
|
+
@relation = r ? r.to_s : nil
|
317
|
+
end
|
318
|
+
|
319
|
+
def ==(i)
|
320
|
+
super(i) and
|
321
|
+
self.names == i.names and
|
322
|
+
self.concepts == i.concepts and
|
323
|
+
self.probability == i.probability and
|
324
|
+
self.relation == i.relation
|
325
|
+
end
|
326
|
+
|
327
|
+
def to_xml(name=nil)
|
328
|
+
el = super(name)
|
329
|
+
|
330
|
+
self.names.each{ |n|
|
331
|
+
name_el = REXML::Element.new("#{obj_ns.prefix}:Name")
|
332
|
+
name_el.text = n
|
333
|
+
el.add_element(name_el)
|
334
|
+
} if self.names
|
335
|
+
|
336
|
+
self.concepts.each{ |c|
|
337
|
+
concept_el = REXML::Element.new("#{obj_ns.prefix}:Concept")
|
338
|
+
concept_el.text = c
|
339
|
+
el.add_element(concept_el)
|
340
|
+
} if self.concepts
|
341
|
+
|
342
|
+
el.attributes["#{obj_ns.prefix}:probability"] = self.probability.to_s if self.probability
|
343
|
+
el.attributes["#{obj_ns.prefix}:relation"] = self.relation if self.relation
|
344
|
+
|
345
|
+
el
|
346
|
+
end
|
347
|
+
|
348
|
+
def self.from_xml(xml)
|
349
|
+
root = element_from(xml)
|
350
|
+
|
351
|
+
names = REXML::XPath.match(root, 'x:Name', {'x' => obj_ns.uri})
|
352
|
+
names = nil if names.size == 0
|
353
|
+
|
354
|
+
concepts = REXML::XPath.match(root, 'x:Concept', {'x' => obj_ns.uri})
|
355
|
+
concepts = nil if concepts.size == 0
|
356
|
+
|
357
|
+
probability = root.attributes.get_attribute_ns(obj_ns.uri, 'probability')
|
358
|
+
relation = root.attributes.get_attribute_ns(obj_ns.uri, 'relation')
|
359
|
+
|
360
|
+
self.new(
|
361
|
+
names ? NameList.new(names.collect{ |name| name.text }) : nil,
|
362
|
+
concepts ? ConceptList.new(concepts.collect{ |concept| concept.text }) : nil,
|
363
|
+
probability ? Float(probability.value) : nil,
|
364
|
+
relation ? relation.value : nil,
|
365
|
+
*Described.described_from_xml(root)
|
366
|
+
)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
class InferenceList < TypedArray
|
371
|
+
def self.restricted_to; [Inference] end
|
372
|
+
end
|
373
|
+
|
374
|
+
# Initial scientific assessment.
|
375
|
+
class Why < Described
|
376
|
+
attr_reader :inferences, :importance, :expires, :names, :concepts
|
377
|
+
|
378
|
+
def initialize(inferences, importance=nil, expires=nil, names=nil, concepts=nil, descriptions=nil, references=nil)
|
379
|
+
super(descriptions, references)
|
380
|
+
self.inferences = inferences
|
381
|
+
self.importance = importance
|
382
|
+
self.expires = expires
|
383
|
+
self.names = names
|
384
|
+
self.concepts = concepts
|
385
|
+
end
|
386
|
+
|
387
|
+
def inferences=(is)
|
388
|
+
if is
|
389
|
+
is = InferenceList.new(is) if is.class == Array
|
390
|
+
raise_type_mismatch_error(is, InferenceList)
|
391
|
+
end
|
392
|
+
|
393
|
+
@inferences = is
|
394
|
+
end
|
395
|
+
|
396
|
+
def importance=(i)
|
397
|
+
i = Float(i) if i
|
398
|
+
@importance = i
|
399
|
+
end
|
400
|
+
|
401
|
+
def expires=(e)
|
402
|
+
if e
|
403
|
+
e = DateTime.parse(e) if e.is_a?(String)
|
404
|
+
raise_type_mismatch_error(e, DateTime)
|
405
|
+
end
|
406
|
+
|
407
|
+
@expires = e
|
408
|
+
end
|
409
|
+
|
410
|
+
def names=(ns)
|
411
|
+
if ns
|
412
|
+
ns = NameList.new(ns) if ns.class == Array
|
413
|
+
raise_type_mismatch_error(ns, NameList)
|
414
|
+
end
|
415
|
+
|
416
|
+
@names = ns
|
417
|
+
end
|
418
|
+
|
419
|
+
def concepts=(cs)
|
420
|
+
if cs
|
421
|
+
cs = ConceptList.new(cs) if cs.class == Array
|
422
|
+
raise_type_mismatch_error(cs, ConceptList)
|
423
|
+
end
|
424
|
+
|
425
|
+
@concepts = cs
|
426
|
+
end
|
427
|
+
|
428
|
+
def ==(w)
|
429
|
+
super(w) and
|
430
|
+
self.inferences == w.inferences and
|
431
|
+
self.importance == w.importance and
|
432
|
+
self.expires == w.expires and
|
433
|
+
self.names == w.names and
|
434
|
+
self.concepts == w.concepts
|
435
|
+
end
|
436
|
+
|
437
|
+
def to_xml(name=nil)
|
438
|
+
el = super(name)
|
439
|
+
|
440
|
+
self.inferences.each{ |i| el.add_element(i.to_xml('Inference')) } if self.inferences
|
441
|
+
|
442
|
+
el.attributes["#{obj_ns.prefix}:importance"] = self.importance.to_s if self.importance
|
443
|
+
el.attributes["#{obj_ns.prefix}:expires"] = self.expires.strftime('%Y-%m-%dT%H:%M:%S') if self.expires
|
444
|
+
|
445
|
+
self.names.each{ |n|
|
446
|
+
name_el = REXML::Element.new("#{obj_ns.prefix}:Name")
|
447
|
+
name_el.text = n
|
448
|
+
el.add_element(name_el)
|
449
|
+
} if self.names
|
450
|
+
|
451
|
+
self.concepts.each{ |c|
|
452
|
+
concept_el = REXML::Element.new("#{obj_ns.prefix}:Concept")
|
453
|
+
concept_el.text = c
|
454
|
+
el.add_element(concept_el)
|
455
|
+
} if self.concepts
|
456
|
+
|
457
|
+
collapse_namespaces(el)
|
458
|
+
el
|
459
|
+
end
|
460
|
+
|
461
|
+
def self.from_xml(xml)
|
462
|
+
root = element_from(xml)
|
463
|
+
|
464
|
+
inferences = REXML::XPath.match(root, 'x:Inference', {'x' => obj_ns.uri})
|
465
|
+
inferences = nil if inferences.size == 0
|
466
|
+
|
467
|
+
names = REXML::XPath.match(root, 'x:Name', {'x' => obj_ns.uri})
|
468
|
+
names = nil if names.size == 0
|
469
|
+
|
470
|
+
concepts = REXML::XPath.match(root, 'x:Concept', {'x' => obj_ns.uri})
|
471
|
+
concepts = nil if concepts.size == 0
|
472
|
+
|
473
|
+
importance = root.attributes.get_attribute_ns(obj_ns.uri, 'importance')
|
474
|
+
expires = root.attributes.get_attribute_ns(obj_ns.uri, 'expires')
|
475
|
+
|
476
|
+
self.new(
|
477
|
+
inferences ? InferenceList.new(inferences.collect{ |i| Inference.from_xml(i) }) : nil,
|
478
|
+
importance ? Float(importance.value) : nil,
|
479
|
+
expires ? DateTime.parse(expires.value) : nil,
|
480
|
+
names ? NameList.new(names.collect{ |n| n.text }) : nil,
|
481
|
+
concepts ? ConceptList.new(concepts.collect{ |c| c.text }) : nil,
|
482
|
+
*Described.described_from_xml(root)
|
483
|
+
)
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
# Instrument Configuration, references to RTML documents.
|
488
|
+
class How < Described; end
|
489
|
+
|
490
|
+
# Space-Time Coordinates, uses the VO STC schema.
|
491
|
+
class WhereWhen < Described
|
492
|
+
class ObsDataLocationList < TypedArray
|
493
|
+
def self.restricted_to; [ObsDataLocation] end
|
494
|
+
end
|
495
|
+
|
496
|
+
attr_reader :obs_data_locations
|
497
|
+
|
498
|
+
def initialize(obs_data_locations=nil, descriptions=nil, references=nil)
|
499
|
+
super(descriptions, references)
|
500
|
+
self.obs_data_locations = obs_data_locations
|
501
|
+
end
|
502
|
+
|
503
|
+
def obs_data_locations=(odls)
|
504
|
+
if odls
|
505
|
+
odls = ObsDataLocationList.new(odls) if odls.class == Array
|
506
|
+
raise_type_mismatch_error(odls, ObsDataLocationList)
|
507
|
+
end
|
508
|
+
|
509
|
+
@obs_data_locations = odls
|
510
|
+
end
|
511
|
+
|
512
|
+
def ==(w)
|
513
|
+
super(w) and
|
514
|
+
self.obs_data_locations == w.obs_data_locations
|
515
|
+
end
|
516
|
+
|
517
|
+
def to_xml(name=nil)
|
518
|
+
el = super(name)
|
519
|
+
|
520
|
+
self.obs_data_locations.each{ |l| el.add_element(l.to_xml) } if self.obs_data_locations
|
521
|
+
|
522
|
+
collapse_namespaces(el)
|
523
|
+
el
|
524
|
+
end
|
525
|
+
|
526
|
+
def self.from_xml(xml)
|
527
|
+
root = element_from(xml)
|
528
|
+
|
529
|
+
locs = REXML::XPath.match(root, 'x:ObsDataLocation', {'x' => obj_ns('VORuby::STC::V1_30').uri})
|
530
|
+
locs = nil if locs.size == 0
|
531
|
+
|
532
|
+
self.new(
|
533
|
+
locs ? ObsDataLocationList.new(locs.collect{ |l| ObsDataLocation.from_xml(l) }) : nil,
|
534
|
+
*Described.described_from_xml(root)
|
535
|
+
)
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
class Param < Base
|
540
|
+
attr_reader :name, :ucd, :value, :unit
|
541
|
+
|
542
|
+
def initialize(name, value, ucd=nil, unit=nil)
|
543
|
+
self.name = name
|
544
|
+
self.value = value
|
545
|
+
self.ucd = ucd
|
546
|
+
self.unit = unit
|
547
|
+
end
|
548
|
+
|
549
|
+
def name=(n)
|
550
|
+
@name = n ? n.to_s : nil
|
551
|
+
end
|
552
|
+
|
553
|
+
def value=(v)
|
554
|
+
@value = v ? v.to_s : nil
|
555
|
+
end
|
556
|
+
|
557
|
+
def ucd=(u)
|
558
|
+
@ucd = u ? u.to_s : nil
|
559
|
+
end
|
560
|
+
|
561
|
+
def unit=(u)
|
562
|
+
@unit = u ? u.to_s : nil
|
563
|
+
end
|
564
|
+
|
565
|
+
def ==(p)
|
566
|
+
self.name == p.name and
|
567
|
+
self.value == p.value and
|
568
|
+
self.ucd == p.ucd and
|
569
|
+
self.unit == p.unit
|
570
|
+
end
|
571
|
+
|
572
|
+
def to_xml(name=nil)
|
573
|
+
el = element(name)
|
574
|
+
|
575
|
+
el.attributes["#{obj_ns.prefix}:name"] = self.name if self.name
|
576
|
+
el.attributes["#{obj_ns.prefix}:value"] = self.value if self.value
|
577
|
+
el.attributes["#{obj_ns.prefix}:ucd"] = self.ucd if self.ucd
|
578
|
+
el.attributes["#{obj_ns.prefix}:unit"] = self.unit if self.unit
|
579
|
+
|
580
|
+
el
|
581
|
+
end
|
582
|
+
|
583
|
+
def self.from_xml(xml)
|
584
|
+
root = element_from(xml)
|
585
|
+
|
586
|
+
name = root.attributes.get_attribute_ns(obj_ns.uri, 'name')
|
587
|
+
value = root.attributes.get_attribute_ns(obj_ns.uri, 'value')
|
588
|
+
ucd = root.attributes.get_attribute_ns(obj_ns.uri, 'ucd')
|
589
|
+
unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
|
590
|
+
|
591
|
+
self.new(
|
592
|
+
name ? name.value : nil,
|
593
|
+
value ? value.value : nil,
|
594
|
+
ucd ? ucd.value : nil,
|
595
|
+
unit ? unit.value : nil
|
596
|
+
)
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
class ParamList < TypedArray
|
601
|
+
def self.restriced_to; [Param] end
|
602
|
+
end
|
603
|
+
|
604
|
+
class Group < Described
|
605
|
+
attr_reader :params, :name, :type
|
606
|
+
|
607
|
+
def initialize(params, name=nil, type=nil, descriptions=nil, references=nil)
|
608
|
+
super(descriptions, references)
|
609
|
+
self.params = params
|
610
|
+
self.name = name
|
611
|
+
self.type = type
|
612
|
+
end
|
613
|
+
|
614
|
+
def params=(ps)
|
615
|
+
if ps
|
616
|
+
ps = ParamList.new(ps) if ps.class == Array
|
617
|
+
raise_type_mismatch_error(ps, ParamList)
|
618
|
+
end
|
619
|
+
|
620
|
+
@params = ps
|
621
|
+
end
|
622
|
+
|
623
|
+
def name=(n)
|
624
|
+
@name = n ? n.to_s : nil
|
625
|
+
end
|
626
|
+
|
627
|
+
def type=(t)
|
628
|
+
@type = t ? t.to_s : nil
|
629
|
+
end
|
630
|
+
|
631
|
+
def ==(g)
|
632
|
+
super(g) and
|
633
|
+
self.params == g.params and
|
634
|
+
self.name == g.name and
|
635
|
+
self.type == g.type
|
636
|
+
end
|
637
|
+
|
638
|
+
def to_xml(name=nil)
|
639
|
+
el = super(name)
|
640
|
+
|
641
|
+
el.attributes["#{obj_ns.prefix}:name"] = self.name if self.name
|
642
|
+
el.attributes["#{obj_ns.prefix}:type"] = self.type if self.type
|
643
|
+
|
644
|
+
self.params.each{ |p| el.add_element(p.to_xml('Param')) } if self.params
|
645
|
+
|
646
|
+
el
|
647
|
+
end
|
648
|
+
|
649
|
+
def self.from_xml(xml)
|
650
|
+
root = element_from(xml)
|
651
|
+
|
652
|
+
params = REXML::XPath.match(root, 'x:Param', {'x' => obj_ns.uri})
|
653
|
+
params = nil if params.size == 0
|
654
|
+
|
655
|
+
name = root.attributes.get_attribute_ns(obj_ns.uri, 'name')
|
656
|
+
type = root.attributes.get_attribute_ns(obj_ns.uri, 'type')
|
657
|
+
|
658
|
+
self.new(
|
659
|
+
params ? ParamList.new(params.collect{ |p| Param.from_xml(p) }) : nil,
|
660
|
+
name ? name.value : nil,
|
661
|
+
type ? type.value : nil,
|
662
|
+
*Described.described_from_xml(root)
|
663
|
+
)
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
class GroupList < TypedArray
|
668
|
+
def self.restricted_to; [Group] end
|
669
|
+
end
|
670
|
+
|
671
|
+
# Event characterization.
|
672
|
+
class What < Described
|
673
|
+
attr_reader :params, :groups
|
674
|
+
|
675
|
+
def initialize(groups, params=nil, descriptions=nil, references=nil)
|
676
|
+
super(descriptions, references)
|
677
|
+
self.groups = groups
|
678
|
+
self.params = params
|
679
|
+
end
|
680
|
+
|
681
|
+
def groups=(gs)
|
682
|
+
if gs
|
683
|
+
gs = GroupList.new(gs) if gs.class == Array
|
684
|
+
raise_type_mismatch_error(gs, GroupList)
|
685
|
+
end
|
686
|
+
|
687
|
+
@groups = gs
|
688
|
+
end
|
689
|
+
|
690
|
+
def params=(ps)
|
691
|
+
if ps
|
692
|
+
ps = ParamList.new(ps) if ps.class == Array
|
693
|
+
raise_type_mismatch_error(ps, ParamList)
|
694
|
+
end
|
695
|
+
|
696
|
+
@params = ps
|
697
|
+
end
|
698
|
+
|
699
|
+
def ==(w)
|
700
|
+
super(w) and
|
701
|
+
self.groups == w.groups and
|
702
|
+
self.params == w.params
|
703
|
+
end
|
704
|
+
|
705
|
+
def to_xml(name=nil)
|
706
|
+
el = super(name)
|
707
|
+
|
708
|
+
self.groups.each{ |g| el.add_element(g.to_xml('Group')) } if self.groups
|
709
|
+
self.params.each{ |p| el.add_element(p.to_xml('Param')) } if self.params
|
710
|
+
|
711
|
+
collapse_namespaces(el)
|
712
|
+
el
|
713
|
+
end
|
714
|
+
|
715
|
+
def self.from_xml(xml)
|
716
|
+
root = element_from(xml)
|
717
|
+
|
718
|
+
groups = REXML::XPath.match(root, 'x:Group', {'x' => obj_ns.uri})
|
719
|
+
groups = nil if groups.size == 0
|
720
|
+
|
721
|
+
params = REXML::XPath.match(root, 'x:Param', {'x' => obj_ns.uri})
|
722
|
+
params = nil if params.size == 0
|
723
|
+
|
724
|
+
self.new(
|
725
|
+
groups ? GroupList.new(groups.collect{ |g| Group.from_xml(g) }) : nil,
|
726
|
+
params ? ParamList.new(params.collect{ |p| Param.from_xml(p) }) : nil,
|
727
|
+
*Described.described_from_xml(root)
|
728
|
+
)
|
729
|
+
end
|
730
|
+
end
|
731
|
+
|
732
|
+
class Author < Base
|
733
|
+
class StringList < TypedArray
|
734
|
+
def self.restriced_to; [String] end
|
735
|
+
end
|
736
|
+
|
737
|
+
attr_reader :titles, :short_names, :logo_urls, :contact_names,
|
738
|
+
:contact_emails, :contact_phones, :contributors
|
739
|
+
|
740
|
+
def initialize(options={})
|
741
|
+
options.each{ |key, value| send("#{key}=", value) }
|
742
|
+
end
|
743
|
+
|
744
|
+
def titles=(ts)
|
745
|
+
if ts
|
746
|
+
ts = StringList.new(ts) if ts.class == Array
|
747
|
+
raise_type_mismatch_error(ts, StringList)
|
748
|
+
end
|
749
|
+
|
750
|
+
@titles = ts
|
751
|
+
end
|
752
|
+
|
753
|
+
def short_names=(sns)
|
754
|
+
if sns
|
755
|
+
sns = StringList.new(sns) if sns.class == Array
|
756
|
+
raise_type_mismatch_error(sns, StringList)
|
757
|
+
end
|
758
|
+
|
759
|
+
@short_names = sns
|
760
|
+
end
|
761
|
+
|
762
|
+
def logo_urls=(lus)
|
763
|
+
if lus
|
764
|
+
lus = StringList.new(lus) if lus.class == Array
|
765
|
+
raise_type_mismatch_error(lus, StringList)
|
766
|
+
end
|
767
|
+
|
768
|
+
@logo_urls = lus
|
769
|
+
end
|
770
|
+
|
771
|
+
def contact_names=(cns)
|
772
|
+
if cns
|
773
|
+
cns = StringList.new(cns) if cns.class == Array
|
774
|
+
raise_type_mismatch_error(cns, StringList)
|
775
|
+
end
|
776
|
+
|
777
|
+
@contact_names = cns
|
778
|
+
end
|
779
|
+
|
780
|
+
def contact_emails=(ces)
|
781
|
+
if ces
|
782
|
+
ces = StringList.new(ces) if ces.class == Array
|
783
|
+
raise_type_mismatch_error(ces, StringList)
|
784
|
+
end
|
785
|
+
|
786
|
+
@contact_emails = ces
|
787
|
+
end
|
788
|
+
|
789
|
+
def contact_phones=(cps)
|
790
|
+
if cps
|
791
|
+
cps = StringList.new(cps) if cps.class == Array
|
792
|
+
raise_type_mismatch_error(cps, StringList)
|
793
|
+
end
|
794
|
+
|
795
|
+
@contact_phones = cps
|
796
|
+
end
|
797
|
+
|
798
|
+
def contributors=(cs)
|
799
|
+
if cs
|
800
|
+
cs = StringList.new(cs) if cs.class == Array
|
801
|
+
raise_type_mismatch_error(cs, StringList)
|
802
|
+
end
|
803
|
+
|
804
|
+
@contributors = cs
|
805
|
+
end
|
806
|
+
|
807
|
+
def ==(a)
|
808
|
+
self.titles == a.titles and
|
809
|
+
self.short_names == a.short_names and
|
810
|
+
self.logo_urls == a.logo_urls and
|
811
|
+
self.contact_names == a.contact_names and
|
812
|
+
self.contact_emails == a.contact_emails and
|
813
|
+
self.contact_phones == a.contact_phones and
|
814
|
+
self.contributors == a.contributors
|
815
|
+
end
|
816
|
+
|
817
|
+
def to_xml(name=nil)
|
818
|
+
el = element(name)
|
819
|
+
|
820
|
+
self.titles.each { |t|
|
821
|
+
e = REXML::Element.new("#{obj_ns.prefix}:title")
|
822
|
+
e.text = t
|
823
|
+
el.add_element(e)
|
824
|
+
} if self.titles
|
825
|
+
|
826
|
+
self.short_names.each{ |n|
|
827
|
+
e = REXML::Element.new("#{obj_ns.prefix}:shortName")
|
828
|
+
e.text = n
|
829
|
+
el.add_element(e)
|
830
|
+
} if self.short_names
|
831
|
+
|
832
|
+
self.logo_urls.each{ |u|
|
833
|
+
e = REXML::Element.new("#{obj_ns.prefix}:logoURL")
|
834
|
+
e.text = u
|
835
|
+
el.add_element(e)
|
836
|
+
} if self.logo_urls
|
837
|
+
|
838
|
+
self.contact_names.each{ |n|
|
839
|
+
e = REXML::Element.new("#{obj_ns.prefix}:contactName")
|
840
|
+
e.text = n
|
841
|
+
el.add_element(e)
|
842
|
+
} if self.contact_names
|
843
|
+
|
844
|
+
self.contact_emails.each{ |m|
|
845
|
+
e = REXML::Element.new("#{obj_ns.prefix}:contactEmail")
|
846
|
+
e.text = m
|
847
|
+
el.add_element(e)
|
848
|
+
} if self.contact_emails
|
849
|
+
|
850
|
+
self.contact_phones.each{ |p|
|
851
|
+
e = REXML::Element.new("#{obj_ns.prefix}:contactPhone")
|
852
|
+
e.text = p
|
853
|
+
el.add_element(e)
|
854
|
+
} if self.contact_phones
|
855
|
+
|
856
|
+
self.contributors.each{ |c|
|
857
|
+
e = REXML::Element.new("#{obj_ns.prefix}:contributor")
|
858
|
+
e.text = c
|
859
|
+
el.add_element(e)
|
860
|
+
} if self.contributors
|
861
|
+
|
862
|
+
el
|
863
|
+
end
|
864
|
+
|
865
|
+
def self.from_xml(xml)
|
866
|
+
root = element_from(xml)
|
867
|
+
|
868
|
+
titles = REXML::XPath.match(root, 'x:title', {'x' => obj_ns.uri})
|
869
|
+
titles = nil if titles.size == 0
|
870
|
+
|
871
|
+
short_names = REXML::XPath.match(root, 'x:shortName', {'x' => obj_ns.uri})
|
872
|
+
short_names = nil if short_names.size == 0
|
873
|
+
|
874
|
+
logo_urls = REXML::XPath.match(root, 'x:logoURL', {'x' => obj_ns.uri})
|
875
|
+
logo_urls = nil if logo_urls.size == 0
|
876
|
+
|
877
|
+
contact_names = REXML::XPath.match(root, 'x:contactName', {'x' => obj_ns.uri})
|
878
|
+
contact_names = nil if contact_names.size == 0
|
879
|
+
|
880
|
+
contact_emails = REXML::XPath.match(root, 'x:contactEmail', {'x' => obj_ns.uri})
|
881
|
+
contact_emails = nil if contact_emails.size == 0
|
882
|
+
|
883
|
+
contact_phones = REXML::XPath.match(root, 'x:contactPhone', {'x' => obj_ns.uri})
|
884
|
+
contact_phones = nil if contact_phones.size == 0
|
885
|
+
|
886
|
+
contributors = REXML::XPath.match(root, 'x:contributor', {'x' => obj_ns.uri})
|
887
|
+
contributors = nil if contributors.size == 0
|
888
|
+
|
889
|
+
self.new(
|
890
|
+
:titles => titles ? StringList.new(titles.collect{ |t| t.text }) : nil,
|
891
|
+
:short_names => short_names ? StringList.new(short_names.collect{ |n| n.text }) : nil,
|
892
|
+
:logo_urls => logo_urls ? StringList.new(logo_urls.collect{ |u| u.text }) : nil,
|
893
|
+
:contact_names => contact_names ? StringList.new(contact_names.collect{ |n| n.text }) : nil,
|
894
|
+
:contact_emails => contact_emails ? StringList.new(contact_emails.collect{ |e| e.text }) : nil,
|
895
|
+
:contact_phones => contact_phones ? StringList.new(contact_phones.collect{ |p| p.text }) : nil,
|
896
|
+
:contributors => contributors ? StringList.new(contributors.collect{ |c| c.text }) : nil
|
897
|
+
)
|
898
|
+
end
|
899
|
+
end
|
900
|
+
|
901
|
+
class Who < Described
|
902
|
+
class IVORNList < TypedArray
|
903
|
+
def self.restricted_to; [URI] end
|
904
|
+
end
|
905
|
+
|
906
|
+
class DateTimeList < TypedArray
|
907
|
+
def self.restricted_to; [DateTime] end
|
908
|
+
end
|
909
|
+
|
910
|
+
class AuthorList < TypedArray
|
911
|
+
def self.restricted_to; [Author] end
|
912
|
+
end
|
913
|
+
|
914
|
+
attr_reader :author_ivorns, :dates, :authors
|
915
|
+
|
916
|
+
def initialize(author_ivorns, dates, authors=nil, descriptions=nil, references=nil)
|
917
|
+
super(descriptions, references)
|
918
|
+
self.author_ivorns = author_ivorns
|
919
|
+
self.dates = dates
|
920
|
+
self.authors = authors
|
921
|
+
end
|
922
|
+
|
923
|
+
def author_ivorns=(ais)
|
924
|
+
if ais
|
925
|
+
ais = IVORNList.new(ais) if ais.class == Array
|
926
|
+
raise_type_mismatch_error(ais, IVORNList)
|
927
|
+
end
|
928
|
+
|
929
|
+
@author_ivorns = ais
|
930
|
+
end
|
931
|
+
|
932
|
+
def dates=(ds)
|
933
|
+
if ds
|
934
|
+
ds = DateTimeList.new(ds) if ds.class == Array
|
935
|
+
raise_type_mismatch_error(ds, DateTimeList)
|
936
|
+
end
|
937
|
+
|
938
|
+
@dates = ds
|
939
|
+
end
|
940
|
+
|
941
|
+
def authors=(as)
|
942
|
+
if as
|
943
|
+
as = AuthorList.new(as) if as.class == Array
|
944
|
+
raise_type_mismatch_error(as, AuthorList)
|
945
|
+
end
|
946
|
+
|
947
|
+
@authors = as
|
948
|
+
end
|
949
|
+
|
950
|
+
def ==(w)
|
951
|
+
super(w) and
|
952
|
+
self.author_ivorns == w.author_ivorns and
|
953
|
+
self.dates == w.dates and
|
954
|
+
self.authors == w.authors
|
955
|
+
end
|
956
|
+
|
957
|
+
def to_xml(name=nil)
|
958
|
+
el = super(name)
|
959
|
+
|
960
|
+
self.author_ivorns.each{ |i|
|
961
|
+
e = REXML::Element.new("#{obj_ns.prefix}:AuthorIVORN")
|
962
|
+
e.text = i.to_s
|
963
|
+
el.add_element(e)
|
964
|
+
} if self.author_ivorns
|
965
|
+
|
966
|
+
self.dates.each{ |d|
|
967
|
+
e = REXML::Element.new("#{obj_ns.prefix}:Date")
|
968
|
+
e.text = d.to_s
|
969
|
+
el.add_element(e)
|
970
|
+
} if self.dates
|
971
|
+
|
972
|
+
self.authors.each{ |a| el.add_element(a.to_xml('Author')) } if self.authors
|
973
|
+
|
974
|
+
collapse_namespaces(el)
|
975
|
+
el
|
976
|
+
end
|
977
|
+
|
978
|
+
def self.from_xml(xml)
|
979
|
+
root = element_from(xml)
|
980
|
+
|
981
|
+
author_ivorns = REXML::XPath.match(root, 'x:AuthorIVORN', {'x' => obj_ns.uri})
|
982
|
+
author_ivorns = nil if author_ivorns.size == 0
|
983
|
+
|
984
|
+
dates = REXML::XPath.match(root, 'x:Date', {'x' => obj_ns.uri})
|
985
|
+
dates = nil if dates.size == 0
|
986
|
+
|
987
|
+
authors = REXML::XPath.match(root, 'x:Author', {'x' => obj_ns.uri})
|
988
|
+
authors = nil if authors.size == 0
|
989
|
+
|
990
|
+
self.new(
|
991
|
+
author_ivorns ? IVORNList.new(author_ivorns.collect{ |i| URI.parse(i.text) }) : nil,
|
992
|
+
dates ? DateTimeList.new(dates.collect{ |d| DateTime.parse(d.text) }) : nil,
|
993
|
+
authors ? AuthorList.new(authors.collect{ |a| Author.from_xml(a) }) : nil,
|
994
|
+
*Described.described_from_xml(root)
|
995
|
+
)
|
996
|
+
end
|
997
|
+
end
|
998
|
+
|
999
|
+
class VOEvent < Described
|
1000
|
+
attr_reader :who, :what, :where_when, :how, :why, :citations,
|
1001
|
+
:version, :ivorn, :role
|
1002
|
+
|
1003
|
+
def initialize(ivorn, who, what, where_when, how, why, version='1.1', role='observation', citations=nil, descriptions=nil, references=nil)
|
1004
|
+
super(descriptions, references)
|
1005
|
+
self.ivorn = ivorn
|
1006
|
+
self.who = who
|
1007
|
+
self.what = what
|
1008
|
+
self.where_when = where_when
|
1009
|
+
self.how = how
|
1010
|
+
self.why = why
|
1011
|
+
self.version = version || '1.1'
|
1012
|
+
self.role = role || 'observation'
|
1013
|
+
self.citations = citations
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
def ivorn=(i)
|
1017
|
+
raise_argument_required_error('IVORN') if !i
|
1018
|
+
|
1019
|
+
i = URI.parse(i) if i.is_a?(String)
|
1020
|
+
raise_type_mismatch_error(i, URI)
|
1021
|
+
|
1022
|
+
@ivorn = i
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
def who=(w)
|
1026
|
+
raise_type_mismatch_error(w, Who) if w
|
1027
|
+
@who = w
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
def what=(w)
|
1031
|
+
raise_type_mismatch_error(w, What) if w
|
1032
|
+
@what = w
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
def where_when=(ww)
|
1036
|
+
raise_type_mismatch_error(ww, WhereWhen) if ww
|
1037
|
+
@where_when = ww
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
def how=(h)
|
1041
|
+
raise_type_mismatch_error(h, How) if h
|
1042
|
+
@how = h
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
def why=(w)
|
1046
|
+
raise_type_mismatch_error(w, Why) if w
|
1047
|
+
@why = w
|
1048
|
+
end
|
1049
|
+
|
1050
|
+
def version=(v)
|
1051
|
+
raise_argument_required_error('version') if !v
|
1052
|
+
@version = v.to_s
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
def role=(r)
|
1056
|
+
@role = r ? r.to_s : nil
|
1057
|
+
end
|
1058
|
+
|
1059
|
+
def citations=(c)
|
1060
|
+
raise_type_mismatch_error(c, Citations) if c
|
1061
|
+
@citations = c
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
def ==(e)
|
1065
|
+
super(e) and
|
1066
|
+
self.who == e.who and
|
1067
|
+
self.what == e.what and
|
1068
|
+
self.where_when == e.where_when and
|
1069
|
+
self.how == e.how and
|
1070
|
+
self.why == e.why and
|
1071
|
+
self.citations == e.citations and
|
1072
|
+
self.version == e.version and
|
1073
|
+
self.ivorn == e.ivorn and
|
1074
|
+
self.role == e.role
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
def to_xml(name='VOEvent')
|
1078
|
+
el = super(name)
|
1079
|
+
|
1080
|
+
el.attributes["#{obj_ns.prefix}:version"] = self.version
|
1081
|
+
el.attributes["#{obj_ns.prefix}:ivorn"] = self.ivorn.to_s
|
1082
|
+
el.attributes["#{obj_ns.prefix}:role"] = self.role if self.role
|
1083
|
+
|
1084
|
+
el.add_element(self.who.to_xml('Who')) if self.who
|
1085
|
+
el.add_element(self.what.to_xml('What')) if self.what
|
1086
|
+
el.add_element(self.where_when.to_xml('WhereWhen')) if self.where_when
|
1087
|
+
el.add_element(self.how.to_xml('How')) if self.how
|
1088
|
+
el.add_element(self.why.to_xml('Why')) if self.why
|
1089
|
+
el.add_element(self.citations.to_xml('Citations')) if self.citations
|
1090
|
+
|
1091
|
+
collapse_namespaces(el)
|
1092
|
+
el
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
def self.from_xml(xml)
|
1096
|
+
root = element_from(xml)
|
1097
|
+
|
1098
|
+
role = root.attributes.get_attribute_ns(obj_ns.uri, 'role')
|
1099
|
+
|
1100
|
+
who = REXML::XPath.first(root, 'x:Who', {'x' => obj_ns.uri})
|
1101
|
+
what = REXML::XPath.first(root, 'x:What', {'x' => obj_ns.uri})
|
1102
|
+
where_when = REXML::XPath.first(root, 'x:WhereWhen', {'x' => obj_ns.uri})
|
1103
|
+
how = REXML::XPath.first(root, 'x:How', {'x' => obj_ns.uri})
|
1104
|
+
why = REXML::XPath.first(root, 'x:Why', {'x' => obj_ns.uri})
|
1105
|
+
citations = REXML::XPath.first(root, 'x:Citations', {'x' => obj_ns.uri})
|
1106
|
+
|
1107
|
+
self.new(
|
1108
|
+
URI.parse(root.attributes.get_attribute_ns(obj_ns.uri, 'ivorn').value),
|
1109
|
+
who ? Who.from_xml(who) : nil,
|
1110
|
+
what ? What.from_xml(what) : nil,
|
1111
|
+
where_when ? WhereWhen.from_xml(where_when) : nil,
|
1112
|
+
how ? How.from_xml(how) : nil,
|
1113
|
+
why ? Why.from_xml(why) : nil,
|
1114
|
+
root.attributes.get_attribute_ns(obj_ns.uri, 'version').value,
|
1115
|
+
role ? role.value : nil,
|
1116
|
+
citations ? Citations.from_xml(citations) : nil,
|
1117
|
+
*Described.described_from_xml(root)
|
1118
|
+
)
|
1119
|
+
end
|
1120
|
+
end
|
1121
|
+
|
1122
|
+
end
|
1123
|
+
end
|
1124
|
+
end
|