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,2418 @@
1
+ require 'voruby/adql/support'
2
+ require 'voruby/stc/1.10/region'
3
+ include VORuby::STC::V1_10::Region
4
+
5
+ module VORuby
6
+ module ADQL
7
+ module V1_0
8
+ include XMLUtilities
9
+
10
+ def element_root(name, type=nil)
11
+ element(name, nil, {:include_xsi => true, :type => type || self.class.xml_type})
12
+ end
13
+
14
+ # The base type for any of items to be selected in a query
15
+ class SelectionItem
16
+ include SerializableToXml
17
+
18
+ def to_xml(name=nil)
19
+ element_root(name)
20
+ end
21
+ end
22
+
23
+ # The base type for a scalar expression
24
+ class ScalarExpression < SelectionItem; end
25
+
26
+ # Represents an expression inside a bracket
27
+ class ClosedExpr < ScalarExpression
28
+ attr_reader :arg
29
+
30
+ def self.xml_type; 'closedExprType' end
31
+
32
+ def initialize(a)
33
+ super()
34
+ self.arg = a
35
+ end
36
+
37
+ def arg=(a)
38
+ raise_argument_required_error('argument') if !a
39
+ raise_type_mismatch_error(a, ScalarExpression)
40
+ @arg = a
41
+ end
42
+
43
+ def to_xml(name=nil)
44
+ el = super(name)
45
+ el.add_element(self.arg.to_xml('Arg'))
46
+
47
+ collapse_namespaces(el)
48
+ el
49
+ end
50
+
51
+ def to_s
52
+ "(#{self.arg})"
53
+ end
54
+
55
+ def ==(e)
56
+ self.arg == e.arg
57
+ end
58
+
59
+ def self.from_xml(xml)
60
+ root = element_from(xml)
61
+
62
+ self.new(
63
+ xml_to_obj(REXML::XPath.first(root, 'x:Arg', {'x' => obj_ns.uri}))
64
+ )
65
+ end
66
+ end
67
+
68
+ # Used for expressing operations like A+B
69
+ class BinaryOperator < Enumeration
70
+ def self.choices; ['+', '-', '*', '/'] end
71
+ end
72
+
73
+ # Represents a binary expression such as a+b
74
+ class BinaryExpr < ScalarExpression
75
+ attr_reader :arg1, :oper, :arg2
76
+
77
+ def self.xml_type; 'binaryExprType' end
78
+
79
+ def initialize(arg1, oper, arg2)
80
+ super()
81
+ self.arg1 = arg1
82
+ self.oper = oper
83
+ self.arg2 = arg2
84
+ end
85
+
86
+ def arg1=(a)
87
+ raise_argument_required_error('argument 1') if !a
88
+ raise_type_mismatch_error(a, ScalarExpression)
89
+ @arg1 = a
90
+ end
91
+
92
+ def oper=(o)
93
+ raise_argument_required_error('operator') if !o
94
+
95
+ o = BinaryOperator.new(o) if o.is_a?(::String)
96
+ raise_type_mismatch_error(o, BinaryOperator)
97
+
98
+ @oper = o
99
+ end
100
+
101
+ def arg2=(a)
102
+ raise_argument_required_error('argument 2') if !a
103
+ raise_type_mismatch_error(a, ScalarExpression)
104
+ @arg2 = a
105
+ end
106
+
107
+ def to_s
108
+ "#{self.arg1} #{self.oper} #{self.arg2}"
109
+ end
110
+
111
+ def to_xml(name=nil)
112
+ el = super(name)
113
+
114
+ el.attributes["#{obj_ns.prefix}:Oper"] = self.oper.to_s
115
+ el.add_element(self.arg1.to_xml('Arg'))
116
+ el.add_element(self.arg2.to_xml('Arg'))
117
+
118
+ collapse_namespaces(el)
119
+ el
120
+ end
121
+
122
+ def ==(e)
123
+ self.arg1 == e.arg1 and
124
+ self.oper == e.oper and
125
+ self.arg2 == e.arg2
126
+ end
127
+
128
+ def self.from_xml(xml)
129
+ root = element_from(xml)
130
+
131
+ args = REXML::XPath.match(root, 'x:Arg', {'x' => obj_ns.uri}).collect{ |a| xml_to_obj(a) }
132
+ self.new(
133
+ args[0],
134
+ BinaryOperator.new(root.attributes.get_attribute_ns(obj_ns.uri, 'Oper').value),
135
+ args[1]
136
+ )
137
+ end
138
+ end
139
+
140
+ # Operators for expressing a single element operation
141
+ class UnaryOperator < Enumeration
142
+ def self.choices; ['+', '-'] end
143
+ end
144
+
145
+ # Represents an unary expression such as -(a.ra)
146
+ class UnaryExpr < ScalarExpression
147
+ attr_reader :arg, :oper
148
+
149
+ def self.xml_type; 'unaryExprType' end
150
+
151
+ def initialize(oper, arg)
152
+ super()
153
+ self.oper = oper
154
+ self.arg = arg
155
+ end
156
+
157
+ def oper=(o)
158
+ raise_argument_required_error('operator') if !o
159
+
160
+ o = UnaryOperator.new(o) if o.is_a?(::String)
161
+ raise_type_mismatch_error(o, UnaryOperator)
162
+
163
+ @oper = o
164
+ end
165
+
166
+ def arg=(a)
167
+ raise_argument_required_error('argument') if !a
168
+ raise_type_mismatch_error(a, ScalarExpression)
169
+ @arg = a
170
+ end
171
+
172
+ def to_xml(name=nil)
173
+ el = super(name)
174
+
175
+ el.attributes["#{obj_ns.prefix}:Oper"] = self.oper.to_s
176
+ el.add_element(self.arg.to_xml('Arg'))
177
+
178
+ collapse_namespaces(el)
179
+ el
180
+ end
181
+
182
+ def to_s
183
+ "#{self.oper}(#{self.arg})"
184
+ end
185
+
186
+ def ==(e)
187
+ self.oper == e.oper and
188
+ self.arg == e.arg
189
+ end
190
+
191
+ def self.from_xml(xml)
192
+ root = element_from(xml)
193
+
194
+ self.new(
195
+ UnaryOperator.new(root.attributes.get_attribute_ns(obj_ns.uri, 'Oper').value),
196
+ xml_to_obj(REXML::XPath.first(root, 'x:Arg', {'x' => obj_ns.uri}))
197
+ )
198
+ end
199
+ end
200
+
201
+ # Represents a column
202
+ class ColumnReference < ScalarExpression
203
+ attr_reader :table, :name, :xpath_name
204
+
205
+ def self.xml_type; 'columnReferenceType' end
206
+
207
+ def initialize(table, name, xpath_name=nil)
208
+ super()
209
+ self.table = table
210
+ self.name = name
211
+ self.xpath_name = xpath_name
212
+ end
213
+
214
+ def table=(t)
215
+ raise_argument_required_error('table') if !t or t.strip == ''
216
+ @table = t.to_s
217
+ end
218
+
219
+ def name=(n)
220
+ raise_argument_required_error('name') if !n or n.strip == ''
221
+ @name = n.to_s
222
+ end
223
+
224
+ def xpath_name=(n)
225
+ @xpath_name = n ? n.to_s : nil
226
+ end
227
+
228
+ def to_xml(name=nil)
229
+ el = super(name)
230
+
231
+ el.attributes["#{obj_ns.prefix}:Table"] = self.table
232
+ el.attributes["#{obj_ns.prefix}:Name"] = self.name
233
+ el.attributes["#{obj_ns.prefix}:xpathName"] = self.xpath_name if self.xpath_name
234
+
235
+ el
236
+ end
237
+
238
+ def to_s
239
+ "#{self.table}.#{self.name}"
240
+ end
241
+
242
+ def ==(r)
243
+ self.table == r.table and
244
+ self.name == r.name and
245
+ self.xpath_name == r.xpath_name
246
+ end
247
+
248
+ def self.from_xml(xml)
249
+ root = element_from(xml)
250
+
251
+ xpath_name = root.attributes.get_attribute_ns(obj_ns.uri, 'xpathName')
252
+ self.new(
253
+ root.attributes.get_attribute_ns(obj_ns.uri, 'Table').value,
254
+ root.attributes.get_attribute_ns(obj_ns.uri, 'Name').value,
255
+ xpath_name ? xpath_name.value : nil
256
+ )
257
+ end
258
+ end
259
+
260
+ # The base type for all literals
261
+ class Literal
262
+ include SerializableToXml
263
+
264
+ attr_reader :value
265
+
266
+ def initialize(v)
267
+ self.value = v
268
+ end
269
+
270
+ def value=(v)
271
+ @value = v
272
+ end
273
+
274
+ def ==(l)
275
+ self.value == l.value
276
+ end
277
+
278
+ def to_s
279
+ self.value.to_s
280
+ end
281
+
282
+ def to_xml(name=nil)
283
+ el = element_root(name)
284
+ el.attributes["#{obj_ns.prefix}:Value"] = self.value.to_s
285
+ el
286
+ end
287
+ end
288
+
289
+ # The base type for all numbers
290
+ class NumberLiteral < Literal; end
291
+
292
+ # Represents a real number
293
+ class RealLiteral < NumberLiteral
294
+ def self.xml_type; 'realType' end
295
+
296
+ def value=(v)
297
+ raise_argument_required_error('value') if v == nil
298
+ super(Float(v))
299
+ end
300
+
301
+ def self.from_xml(xml)
302
+ root = element_from(xml)
303
+ self.new(
304
+ Float(root.attributes.get_attribute_ns(obj_ns.uri, 'Value').value)
305
+ )
306
+ end
307
+ end
308
+
309
+ # Represents an integer
310
+ class IntegerLiteral < NumberLiteral
311
+ def self.xml_type; 'integerType' end
312
+
313
+ def value=(v)
314
+ raise_argument_required_error('value') if v == nil
315
+ super(Integer(v))
316
+ end
317
+
318
+ def self.from_xml(xml)
319
+ root = element_from(xml)
320
+ self.new(
321
+ Integer(root.attributes.get_attribute_ns(obj_ns.uri, 'Value').value)
322
+ )
323
+ end
324
+ end
325
+
326
+ # Represents a string literal
327
+ class StringLiteral < Literal
328
+ def self.xml_type; 'stringType' end
329
+
330
+ def value=(v)
331
+ raise_argument_required_error('value') if v == nil
332
+ super(v.to_s)
333
+ end
334
+
335
+ def to_s
336
+ "'#{super}'"
337
+ end
338
+
339
+ def self.from_xml(xml)
340
+ root = element_from(xml)
341
+ self.new(
342
+ root.attributes.get_attribute_ns(obj_ns.uri, 'Value').value
343
+ )
344
+ end
345
+ end
346
+
347
+ # Encapsulates basic literals such as Strings, Integers and Real numbers
348
+ class Atom < ScalarExpression
349
+ attr_reader :literal, :unit
350
+
351
+ def self.xml_type; 'atomType' end
352
+
353
+ def initialize(l, u=nil)
354
+ super()
355
+ self.literal = l
356
+ self.unit = u
357
+ end
358
+
359
+ def literal=(l)
360
+ raise_argument_required_error('literal') if !l
361
+
362
+ if !l.is_a?(Literal)
363
+ if l.is_a?(::String)
364
+ l = StringLiteral.new(l)
365
+ elsif l.is_a?(Float)
366
+ l = RealLiteral.new(l)
367
+ elsif l.is_a?(Fixnum)
368
+ l = IntegerLiteral.new(l)
369
+ end
370
+ end
371
+ raise_type_mismatch_error(l, Literal)
372
+
373
+ @literal = l
374
+ end
375
+
376
+ def unit=(u)
377
+ @unit = u ? u.to_s : nil
378
+ end
379
+
380
+ def ==(a)
381
+ self.literal == a.literal and
382
+ self.unit == a.unit
383
+ end
384
+
385
+ def to_s
386
+ self.literal.to_s
387
+ end
388
+
389
+ def to_xml(name=nil)
390
+ el = super(name)
391
+
392
+ el.add_element(self.literal.to_xml('Literal'))
393
+
394
+ if self.unit
395
+ unit_el = element('Unit')
396
+ unit_el.text = self.unit.to_s
397
+ el.add_element(unit_el)
398
+ end
399
+
400
+ collapse_namespaces(el)
401
+ el
402
+ end
403
+
404
+ def self.from_xml(xml)
405
+ root = element_from(xml)
406
+
407
+ unit_el = REXML::XPath.first(root, 'x:Unit', {'x' => obj_ns.uri})
408
+ unit = unit_el ? unit_el.text : nil
409
+
410
+ self.new(
411
+ xml_to_obj(REXML::XPath.first(root, 'x:Literal', {'x' => obj_ns.uri})),
412
+ unit
413
+ )
414
+ end
415
+ end
416
+
417
+ # Enumeration for All and Distinct options
418
+ class AllOrDistinct < Enumeration
419
+ def self.choices; ['All', 'DISTINCT'] end
420
+ end
421
+
422
+ # Option of selecting all or distinct elements in a query
423
+ class SelectionOption
424
+ include SerializableToXml
425
+
426
+ attr_reader :option
427
+
428
+ def self.xml_type; 'selectionOptionType' end
429
+
430
+ def initialize(option)
431
+ self.option = option
432
+ end
433
+
434
+ def option=(o)
435
+ raise_argument_required_error('option') if !o
436
+
437
+ o = AllOrDistinct.new(o) if o.is_a?(::String)
438
+ raise_type_mismatch_error(o, AllOrDistinct)
439
+
440
+ @option = o
441
+ end
442
+
443
+ def ==(o)
444
+ self.option == o.option
445
+ end
446
+
447
+ def to_s
448
+ self.option.to_s
449
+ end
450
+
451
+ def to_xml(name=nil)
452
+ el = element_root(name)
453
+ el.attributes["#{obj_ns.prefix}:Option"] = self.option.to_s
454
+ el
455
+ end
456
+
457
+ def self.from_xml(xml)
458
+ root = element_from(xml)
459
+
460
+ self.new(
461
+ AllOrDistinct.new(root.attributes.get_attribute_ns(obj_ns.uri, 'Option').value)
462
+ )
463
+ end
464
+ end
465
+
466
+ # The base type for a function
467
+ class Function < ScalarExpression
468
+ attr_reader :arg, :allow, :name
469
+
470
+ def initialize(arg, allow=nil)
471
+ super()
472
+ self.arg = arg
473
+ self.allow = allow
474
+ end
475
+
476
+ def arg=(a)
477
+ raise_argument_required_error('argument') if !a
478
+ raise_type_mismatch_error(a, SelectionItem)
479
+ @arg = a
480
+ end
481
+
482
+ def allow=(a)
483
+ raise_type_mismatch_error(a, SelectionOption) if a
484
+ @allow = a
485
+ end
486
+
487
+ def ==(f)
488
+ self.name == f.name and
489
+ self.arg == f.arg and
490
+ self.allow == f.allow
491
+ end
492
+
493
+ def to_xml(name=nil)
494
+ el = super(name)
495
+
496
+ el.attributes["#{obj_ns.prefix}:Name"] = self.name.to_s
497
+ el.add_element(self.allow.to_xml('Allow')) if self.allow
498
+ el.add_element(self.arg.to_xml('Arg'))
499
+
500
+ collapse_namespaces(el)
501
+ el
502
+ end
503
+
504
+ def to_s
505
+ f = "#{self.name}(#{self.arg})"
506
+ f = "#{self.allow} #{f}" if self.allow
507
+ f
508
+ end
509
+ end
510
+
511
+ # Enumeration of allowed trigonometric functions
512
+ class TrigonometricFunctionName < Enumeration
513
+ def self.choices; ['SIN', 'COS', 'TAN', 'COT', 'ASIN', 'ACOS', 'ATAN', 'ATAN2'] end
514
+ end
515
+
516
+ # Represents a trigonometric function
517
+ class TrigonometricFunction < Function
518
+ def self.xml_type; 'trigonometricFunctionType' end
519
+
520
+ def initialize(name, arg, allow=nil)
521
+ super(arg, allow)
522
+ self.name = name
523
+ end
524
+
525
+ def name=(n)
526
+ raise_argument_required_error('trigonometric function name') if !n
527
+
528
+ n = TrigonometricFunctionName.new(n) if n.is_a?(::String)
529
+ raise_type_mismatch_error(n, TrigonometricFunctionName)
530
+
531
+ @name = n
532
+ end
533
+
534
+ def self.from_xml(xml)
535
+ root = element_from(xml)
536
+
537
+ allow_el = REXML::XPath.first(root, 'x:Allow', {'x' => obj_ns.uri})
538
+ self.new(
539
+ TrigonometricFunctionName.new(root.attributes.get_attribute_ns(obj_ns.uri, 'Name').value),
540
+ xml_to_obj(REXML::XPath.first(root, 'x:Arg', {'x' => obj_ns.uri})),
541
+ allow_el ? xml_to_obj(allow_el) : nil
542
+ )
543
+ end
544
+ end
545
+
546
+ # Enumeration of allowed math functions
547
+ class MathFunctionName < Enumeration
548
+ def self.choices
549
+ ['ABS', 'CEILING', 'DEGREES', 'EXP', 'FLOOR',
550
+ 'LOG', 'PI', 'POWER', 'RADIANS', 'SQRT',
551
+ 'SQUARE', 'LOG10', 'RAND', 'ROUND', 'TRUNCATE']
552
+ end
553
+ end
554
+
555
+ # Represents a math function
556
+ class MathFunction < Function
557
+ def self.xml_type; 'mathFunctionType' end
558
+
559
+ def initialize(name, arg, allow=nil)
560
+ super(arg, allow)
561
+ self.name = name
562
+ end
563
+
564
+ def name=(n)
565
+ raise_argument_required_error('math function name') if !n
566
+
567
+ n = MathFunctionName.new(n) if n.is_a?(::String)
568
+ raise_type_mismatch_error(n, MathFunctionName)
569
+
570
+ @name = n
571
+ end
572
+
573
+ def self.from_xml(xml)
574
+ root = element_from(xml)
575
+
576
+ allow_el = REXML::XPath.first(root, 'x:Allow', {'x' => obj_ns.uri})
577
+ self.new(
578
+ MathFunctionName.new(root.attributes.get_attribute_ns(obj_ns.uri, 'Name').value),
579
+ xml_to_obj(REXML::XPath.first(root, 'x:Arg', {'x' => obj_ns.uri})),
580
+ allow_el ? xml_to_obj(allow_el) : nil
581
+ )
582
+ end
583
+ end
584
+
585
+ # Enumeration of allowed aggregate functions
586
+ class AggregateFunctionName < Enumeration
587
+ def self.choices; ['AVG', 'MIN', 'MAX', 'SUM', 'COUNT'] end
588
+ end
589
+
590
+ # Represents an aggregate function
591
+ class AggregateFunction < Function
592
+ def self.xml_type; 'aggregateFunctionType' end
593
+
594
+ def initialize(name, arg, allow=nil)
595
+ super(arg, allow)
596
+ self.name = name
597
+ end
598
+
599
+ def name=(n)
600
+ raise_argument_required_error('aggregate function name') if !n
601
+
602
+ n = AggregateFunctionName.new(n) if n.is_a?(::String)
603
+ raise_type_mismatch_error(n, AggregateFunctionName)
604
+
605
+ @name = n
606
+ end
607
+
608
+ def self.from_xml(xml)
609
+ root = element_from(xml)
610
+
611
+ allow_el = REXML::XPath.first(root, 'x:Allow', {'x' => obj_ns.uri})
612
+ self.new(
613
+ AggregateFunctionName.new(root.attributes.get_attribute_ns(obj_ns.uri, 'Name').value),
614
+ xml_to_obj(REXML::XPath.first(root, 'x:Arg', {'x' => obj_ns.uri})),
615
+ allow_el ? xml_to_obj(allow_el) : nil
616
+ )
617
+ end
618
+ end
619
+
620
+ # Represents user defined function expressions
621
+ class UserDefinedFunction < ScalarExpression
622
+ class ListOfScalarExpression < TypedArray
623
+ def self.restricted_to; [ScalarExpression] end
624
+ end
625
+
626
+ attr_reader :name, :params
627
+
628
+ def self.xml_type; 'userDefinedFunctionType' end
629
+
630
+ def initialize(name, params=nil)
631
+ self.name = name
632
+ self.params = params
633
+ end
634
+
635
+ def name=(n)
636
+ raise_argument_required_error('name') if !n
637
+ @name = n.to_s
638
+ end
639
+
640
+ def params=(ps)
641
+ if ps
642
+ ps = UserDefinedFunction::ListOfScalarExpression.new(ps) if ps.class == Array
643
+ raise_type_mismatch_error(ps, UserDefinedFunction::ListOfScalarExpression)
644
+ end
645
+
646
+ @params = ps
647
+ end
648
+
649
+ def ==(f)
650
+ self.name == f.name and
651
+ self.params == f.params
652
+ end
653
+
654
+ def to_s
655
+ s = "#{self.name}("
656
+ s << self.params.collect{ |p| p.to_s }.join(', ') if self.params
657
+ s << ')'
658
+ s
659
+ end
660
+
661
+ def to_xml(name=nil)
662
+ el = super(name)
663
+
664
+ name_el = REXML::Element.new("#{obj_ns.prefix}:Name")
665
+ name_el.text = self.name
666
+ el.add_element(name_el)
667
+
668
+ self.params.each{ |p| el.add_element(p.to_xml('Params'))} if self.params
669
+
670
+ el
671
+ end
672
+
673
+ def self.from_xml(xml)
674
+ root = element_from(xml)
675
+
676
+ params_el = REXML::XPath.match(root, 'x:Params', {'x' => obj_ns.uri})
677
+ params = params_el ?
678
+ UserDefinedFunction::ListOfScalarExpression.new(params_el.collect{ |pel| xml_to_obj(pel) }) :
679
+ nil
680
+
681
+ self.new(
682
+ REXML::XPath.first(root, 'x:Name', {'x' => obj_ns.uri}).text,
683
+ params
684
+ )
685
+ end
686
+ end
687
+
688
+ # Used to select an expression as a new alias column
689
+ class AliasSelectionItem < SelectionItem
690
+ attr_reader :expression, :as
691
+
692
+ def self.xml_type; 'aliasSelectionItemType' end
693
+
694
+ def initialize(expression, as=nil)
695
+ self.expression = expression
696
+ self.as = as
697
+ end
698
+
699
+ def expression=(e)
700
+ raise_argument_required_error('expression') if !e
701
+ raise_type_mismatch_error(e, ScalarExpression)
702
+ @expression = e
703
+ end
704
+
705
+ def as=(a)
706
+ @as = a ? a.to_s : nil
707
+ end
708
+
709
+ def ==(a)
710
+ self.expression == a.expression and
711
+ self.as == a.as
712
+ end
713
+
714
+ def to_s
715
+ a = self.expression.to_s
716
+ a = "#{a} AS #{as}" if self.as
717
+ a
718
+ end
719
+
720
+ def to_xml(name=nil)
721
+ el = super(name)
722
+
723
+ el.attributes["#{obj_ns.prefix}:As"] = self.as if self.as
724
+ el.add_element(self.expression.to_xml('Expression'))
725
+
726
+ collapse_namespaces(el)
727
+ el
728
+ end
729
+
730
+ def self.from_xml(xml)
731
+ root = element_from(xml)
732
+
733
+ as = root.attributes.get_attribute_ns(obj_ns.uri, 'As')
734
+ self.new(
735
+ xml_to_obj(REXML::XPath.first(root, 'x:Expression', {'x' => obj_ns.uri})),
736
+ as ? as.value : nil
737
+ )
738
+ end
739
+ end
740
+
741
+ # Represent all columns as in Select * query
742
+ class AllSelectionItem < SelectionItem
743
+ def self.xml_type; 'allSelectionItemType' end
744
+
745
+ def to_s; '*' end
746
+
747
+ def to_xml(name=nil)
748
+ super(name)
749
+ end
750
+
751
+ def ==(a)
752
+ self.class == a.class
753
+ end
754
+
755
+ def self.from_xml(xml)
756
+ self.new
757
+ end
758
+ end
759
+
760
+ # The Comparison operators such as Less-than or More-than, etc
761
+ class Comparison < Enumeration
762
+ def self.choices; ['=', '<>', '>', '>=', '<', '<='] end
763
+ end
764
+
765
+ # The base type for all tables used in the From clause of the query
766
+ class FromTable
767
+ include SerializableToXml
768
+
769
+ def to_xml(name=nil)
770
+ element_root(name)
771
+ end
772
+ end
773
+
774
+ # Same as a Table with an additional archive name
775
+ class ArchiveTable < FromTable
776
+ attr_reader :archive, :name, :table_alias
777
+
778
+ def self.xml_type; 'archiveTableType' end
779
+
780
+ def initialize(archive, name, table_alias=nil)
781
+ self.archive = archive
782
+ self.name = name
783
+ self.table_alias = table_alias
784
+ end
785
+
786
+ def archive=(a)
787
+ raise_argument_required_error('archive') if !a or a.to_s.strip == ''
788
+ @archive = a.to_s
789
+ end
790
+
791
+ def name=(n)
792
+ raise_argument_required_error('name') if !n or n.to_s.strip == ''
793
+ @name = n.to_s
794
+ end
795
+
796
+ def table_alias=(a)
797
+ @table_alias = a ? a.to_s : nil
798
+ end
799
+
800
+ def ==(t)
801
+ self.archive == t.archive and
802
+ self.name == t.name and
803
+ self.table_alias == t.table_alias
804
+ end
805
+
806
+ def to_s
807
+ t = "#{self.archive}:#{self.name}"
808
+ t = "#{t} #{self.table_alias}" if self.table_alias
809
+ t
810
+ end
811
+
812
+ def to_xml(name=nil)
813
+ el = super(name)
814
+
815
+ el.attributes["#{obj_ns.prefix}:Archive"] = self.archive
816
+ el.attributes["#{obj_ns.prefix}:Name"] = self.name
817
+ el.attributes["#{obj_ns.prefix}:Alias"] = self.table_alias if self.table_alias
818
+
819
+ el
820
+ end
821
+
822
+ def self.from_xml(xml)
823
+ root = element_from(xml)
824
+
825
+ table_alias = root.attributes.get_attribute_ns(obj_ns.uri, 'Alias')
826
+ self.new(
827
+ root.attributes.get_attribute_ns(obj_ns.uri, 'Archive').value,
828
+ root.attributes.get_attribute_ns(obj_ns.uri, 'Name').value,
829
+ table_alias ? table_alias.value : nil
830
+ )
831
+ end
832
+ end
833
+
834
+ # Represents a table with its name and its alias name
835
+ class Table < FromTable
836
+ attr_reader :name, :table_alias, :xpath_name
837
+
838
+ def self.xml_type; 'tableType' end
839
+
840
+ def initialize(name, table_alias=nil, xpath_name=nil)
841
+ self.name = name
842
+ self.table_alias = table_alias
843
+ self.xpath_name = xpath_name
844
+ end
845
+
846
+ def name=(n)
847
+ raise_argument_required_error('name') if !n or n.to_s.strip == ''
848
+ @name = n.to_s
849
+ end
850
+
851
+ def table_alias=(a)
852
+ @table_alias = a ? a.to_s : nil
853
+ end
854
+
855
+ def xpath_name=(p)
856
+ @xpath_name = p ? p.to_s : nil
857
+ end
858
+
859
+ def ==(t)
860
+ self.name == t.name and
861
+ self.table_alias == t.table_alias and
862
+ self.xpath_name == t.xpath_name
863
+ end
864
+
865
+ def to_s
866
+ t = self.name
867
+ t = "#{t} #{self.table_alias}" if self.table_alias
868
+ t
869
+ end
870
+
871
+ def to_xml(name=nil)
872
+ el = super(name)
873
+
874
+ el.attributes["#{obj_ns.prefix}:Name"] = self.name
875
+ el.attributes["#{obj_ns.prefix}:Alias"] = self.table_alias if self.table_alias
876
+ el.attributes["#{obj_ns.prefix}:xpathName"] = self.xpath_name if self.xpath_name
877
+
878
+ el
879
+ end
880
+
881
+ def self.from_xml(xml)
882
+ root = element_from(xml)
883
+
884
+ table_alias = root.attributes.get_attribute_ns(obj_ns.uri, 'Alias')
885
+ xpath_name = root.attributes.get_attribute_ns(obj_ns.uri, 'xpathName')
886
+ self.new(
887
+ root.attributes.get_attribute_ns(obj_ns.uri, 'Name').value,
888
+ table_alias ? table_alias.value : nil,
889
+ xpath_name ? xpath_name.value : nil
890
+ )
891
+ end
892
+ end
893
+
894
+ # Denotes the type of a Join operation
895
+ class JointTableQualifier < Enumeration
896
+ def self.choices; ['LEFT_OUTER', 'RIGHT_OUTER', 'FULL_OUTER', 'INNER', 'CROSS'] end
897
+ end
898
+
899
+ # Represents SQL JOIN expression
900
+ class JoinTable < FromTable
901
+ class ListOfFromTable < TypedArray
902
+ def self.restricted_to; [FromTable] end
903
+ def self.minimum_length; 1 end
904
+ end
905
+
906
+ attr_reader :qualifier, :tables, :condition
907
+
908
+ def self.xml_type; 'joinTableType' end
909
+
910
+ def initialize(qualifier, tables, condition)
911
+ self.qualifier = qualifier
912
+ self.tables = tables
913
+ self.condition = condition
914
+ end
915
+
916
+ def qualifier=(q)
917
+ raise_argument_required_error('qualifier') if !q
918
+
919
+ q = JointTableQualifier.new(q) if q.is_a?(String)
920
+ raise_type_mismatch_error(q, JointTableQualifier)
921
+
922
+ @qualifier = q
923
+ end
924
+
925
+ def tables=(ts)
926
+ raise_argument_required_error('tables') if !ts
927
+
928
+ ts = JoinTable::ListOfFromTable.new(ts) if ts.class == Array
929
+ raise_type_mismatch_error(ts, JoinTable::ListOfFromTable)
930
+
931
+ @tables = ts
932
+ end
933
+
934
+ def condition=(c)
935
+ raise_argument_required_error('condition') if !c
936
+ raise_type_mismatch_error(c, ComparisonPred)
937
+ @condition = c
938
+ end
939
+
940
+ def ==(t)
941
+ self.qualifier == t.qualifier and
942
+ self.tables == t.tables and
943
+ self.condition == t.condition
944
+ end
945
+
946
+ def to_s
947
+ "#{self.qualifier} #{self.tables.collect{ |t| t.to_s}.join(', ')} ON #{self.condition}"
948
+ end
949
+
950
+ def to_xml(name=nil)
951
+ el = super(name)
952
+
953
+ qualifier = REXML::Element.new("#{obj_ns.prefix}:Qualifier")
954
+ qualifier.text = self.qualifier.to_s
955
+ el.add_element(qualifier)
956
+
957
+ self.tables.collect{ |t| el.add_element(t.to_xml('Table')) }
958
+
959
+ el.add_element(self.condition.to_xml('Condition'))
960
+
961
+ collapse_namespaces(el)
962
+ el
963
+ end
964
+
965
+ def self.from_xml(xml)
966
+ root = element_from(xml)
967
+
968
+ self.new(
969
+ JointTableQualifier.new(REXML::XPath.first(root, 'x:Qualifier', {'x' => obj_ns.uri}).text),
970
+ JoinTable::ListOfFromTable.new(
971
+ REXML::XPath.match(root, 'x:Table', {'x' => obj_ns.uri}).collect{ |tel| xml_to_obj(tel) }
972
+ ),
973
+ xml_to_obj(REXML::XPath.first(root, 'x:Condition', {'x' => obj_ns.uri}))
974
+ )
975
+ end
976
+ end
977
+
978
+ # The base type for all table inclusion or drop types used in a cross match expression
979
+ class XMatchTableAlias
980
+ include SerializableToXml
981
+
982
+ attr_reader :name
983
+
984
+ def initialize(name)
985
+ self.name = name
986
+ end
987
+
988
+ def name=(n)
989
+ raise_argument_required_error('name') if !n or n.to_s.strip == ''
990
+ @name = n.to_s
991
+ end
992
+
993
+ def ==(t)
994
+ self.name == t.name
995
+ end
996
+
997
+ def to_xml(name=nil)
998
+ el = element_root(name)
999
+ el.attributes["#{obj_ns.prefix}:Name"] = self.name
1000
+ el
1001
+ end
1002
+
1003
+ def self.from_xml(xml=nil)
1004
+ root = element_from(xml)
1005
+ self.new(root.attributes.get_attribute_ns(obj_ns.uri, 'Name'))
1006
+ end
1007
+ end
1008
+
1009
+ # Used for adding a table for the Xmatch operation
1010
+ class IncludeTable < XMatchTableAlias
1011
+ def self.xml_type; 'includeTableType' end
1012
+
1013
+ def to_s
1014
+ self.name
1015
+ end
1016
+ end
1017
+
1018
+ # Used for avoiding a table in Xmatch
1019
+ class DropTable < XMatchTableAlias
1020
+ def self.xml_type; 'dropTableType' end
1021
+
1022
+ def to_s
1023
+ "!#{self.name}"
1024
+ end
1025
+ end
1026
+
1027
+ # The base type for searches in Where and Having clauses of the query
1028
+ class Search
1029
+ include SerializableToXml
1030
+
1031
+ def to_xml(name=nil)
1032
+ element_root(name)
1033
+ end
1034
+ end
1035
+
1036
+ # Represents expressions like A And B
1037
+ class IntersectionSearch < Search
1038
+ attr_reader :condition1, :condition2
1039
+
1040
+ def self.xml_type; 'intersectionSearchType' end
1041
+
1042
+ def initialize(condition1, condition2)
1043
+ self.condition1 = condition1
1044
+ self.condition2 = condition2
1045
+ end
1046
+
1047
+ def condition1=(c)
1048
+ raise_argument_required_error('condition 1') if !c
1049
+ raise_type_mismatch_error(c, Search)
1050
+ @condition1 = c
1051
+ end
1052
+
1053
+ def condition2=(c)
1054
+ raise_argument_required_error('condition 2') if !c
1055
+ raise_type_mismatch_error(c, Search)
1056
+ @condition2 = c
1057
+ end
1058
+
1059
+ def ==(s)
1060
+ self.condition1 == s.condition1 and
1061
+ self.condition2 == s.condition2
1062
+ end
1063
+
1064
+ def to_s
1065
+ "#{self.condition1} AND #{self.condition2}"
1066
+ end
1067
+
1068
+ def to_xml(name=nil)
1069
+ el = super(name)
1070
+
1071
+ el.add_element(self.condition1.to_xml('Condition'))
1072
+ el.add_element(self.condition2.to_xml('Condition'))
1073
+
1074
+ collapse_namespaces(el)
1075
+ el
1076
+ end
1077
+
1078
+ def self.from_xml(xml)
1079
+ root = element_from(xml)
1080
+
1081
+ conds = REXML::XPath.match(root, 'x:Condition', {'x' => obj_ns.uri})
1082
+ self.new(xml_to_obj(conds[0]), xml_to_obj(conds[1]))
1083
+ end
1084
+ end
1085
+
1086
+ # Represents expressions like A Or B
1087
+ class UnionSearch < Search
1088
+ attr_reader :condition1, :condition2
1089
+
1090
+ def self.xml_type; 'unionSearchType' end
1091
+
1092
+ def initialize(condition1, condition2)
1093
+ self.condition1 = condition1
1094
+ self.condition2 = condition2
1095
+ end
1096
+
1097
+ def condition1=(c)
1098
+ raise_argument_required_error('condition 1') if !c
1099
+ raise_type_mismatch_error(c, Search)
1100
+ @condition1 = c
1101
+ end
1102
+
1103
+ def condition2=(c)
1104
+ raise_argument_required_error('condition 2') if !c
1105
+ raise_type_mismatch_error(c, Search)
1106
+ @condition2 = c
1107
+ end
1108
+
1109
+ def ==(s)
1110
+ self.condition1 == s.condition1 and
1111
+ self.condition2 == s.condition2
1112
+ end
1113
+
1114
+ def to_s
1115
+ "#{self.condition1} OR #{self.condition2}"
1116
+ end
1117
+
1118
+ def to_xml(name=nil)
1119
+ el = super(name)
1120
+
1121
+ el.add_element(self.condition1.to_xml('Condition'))
1122
+ el.add_element(self.condition2.to_xml('Condition'))
1123
+
1124
+ collapse_namespaces(el)
1125
+ el
1126
+ end
1127
+
1128
+ def self.from_xml(xml)
1129
+ root = element_from(xml)
1130
+
1131
+ conds = REXML::XPath.match(root, 'x:Condition', {'x' => obj_ns.uri})
1132
+ self.new(xml_to_obj(conds[0]), xml_to_obj(conds[1]))
1133
+ end
1134
+ end
1135
+
1136
+ # A cross match expression
1137
+ class XMatch < Search
1138
+ attr_reader :tables, :nature, :sigma
1139
+
1140
+ def self.xml_type; 'xMatchType' end
1141
+
1142
+ class XMatchTableAliasList < TypedArray
1143
+ def self.restricted_to; [XMatchTableAlias] end
1144
+ def self.minimum_length; 2 end
1145
+ end
1146
+
1147
+ def initialize(tables, nature, sigma)
1148
+ self.tables = tables
1149
+ self.nature = nature
1150
+ self.sigma = sigma
1151
+ end
1152
+
1153
+ def tables=(ts)
1154
+ raise_argument_required_error('tables') if !ts
1155
+
1156
+ ts = XMatchTableAliasList.new(ts) if ts.class == Array
1157
+ raise_type_mismatch_error(ts, XMatchTableAliasList)
1158
+
1159
+ @tables = ts
1160
+ end
1161
+
1162
+ def nature=(n)
1163
+ raise_argument_required_error('nature') if !n
1164
+
1165
+ n = Comparison.new(n) if n.is_a?(::String)
1166
+ raise_type_mismatch_error(n, Comparison)
1167
+
1168
+ @nature = n
1169
+ end
1170
+
1171
+ def sigma=(s)
1172
+ raise_argument_required_error('sigma') if !s
1173
+
1174
+ if s.is_a?(Fixnum)
1175
+ s = IntegerLiteral.new(s)
1176
+ elsif s.is_a?(Float)
1177
+ s = RealLiteral.new(s)
1178
+ end
1179
+ raise_type_mismatch_error(s, NumberLiteral)
1180
+
1181
+ @sigma = s
1182
+ end
1183
+
1184
+ def ==(m)
1185
+ self.tables == m.tables and
1186
+ self.nature == m.nature and
1187
+ self.sigma == m.sigma
1188
+ end
1189
+
1190
+ def to_s
1191
+ "XMATCH(#{self.tables.collect{ |t| t.to_s }.join(', ')}) #{self.nature} #{self.sigma}"
1192
+ end
1193
+
1194
+ def to_xml(name=nil)
1195
+ el = super(name)
1196
+
1197
+ self.tables.each{ |t| el.add_element(t.to_xml('Table')) }
1198
+
1199
+ nature = element_root('Nature', 'comparisonType')
1200
+ nature.text = self.nature.to_s
1201
+ el.add_element(nature)
1202
+
1203
+ el.add_element(self.sigma.to_xml('Sigma'))
1204
+
1205
+ collapse_namespaces(el)
1206
+ el
1207
+ end
1208
+
1209
+ def self.from_xml(xml)
1210
+ root = element_from(xml)
1211
+
1212
+ self.new(
1213
+ XMatchTableAliasList.new(
1214
+ REXML::XPath.match(root, 'x:Table', {'x' => obj_ns.uri}).collect{ |el| xml_to_obj(el) }
1215
+ ),
1216
+ Comparison.new(REXML::XPath.first(root, 'x:Nature', {'x' => obj_ns.uri}).text),
1217
+ xml_to_obj(REXML::XPath.first(root, 'x:Sigma', {'x' => obj_ns.uri}))
1218
+ )
1219
+ end
1220
+ end
1221
+
1222
+ # The Like expression of a query
1223
+ class LikePred < Search
1224
+ attr_reader :arg, :pattern
1225
+
1226
+ def self.xml_type; 'likePredType' end
1227
+
1228
+ def initialize(arg, pattern)
1229
+ self.arg = arg
1230
+ self.pattern = pattern
1231
+ end
1232
+
1233
+ def arg=(a)
1234
+ raise_argument_required_error('argument') if !a
1235
+ raise_type_mismatch_error(a, ScalarExpression)
1236
+ @arg = a
1237
+ end
1238
+
1239
+ def pattern=(p)
1240
+ raise_argument_required_error('pattern') if !p
1241
+
1242
+ p = Atom.new(p) if !p.is_a?(Atom)
1243
+ raise_type_mismatch_error(p, Atom)
1244
+
1245
+ @pattern = p
1246
+ end
1247
+
1248
+ def ==(p)
1249
+ self.arg == p.arg and
1250
+ self.pattern == p.pattern
1251
+ end
1252
+
1253
+ def to_s
1254
+ "#{arg} LIKE #{pattern}"
1255
+ end
1256
+
1257
+ def to_xml(name=nil)
1258
+ el = super(name)
1259
+
1260
+ el.add_element(self.arg.to_xml('Arg'))
1261
+ el.add_element(self.pattern.to_xml('Pattern'))
1262
+
1263
+ collapse_namespaces(el)
1264
+ el
1265
+ end
1266
+
1267
+ def self.from_xml(xml)
1268
+ root = element_from(xml)
1269
+
1270
+ self.new(
1271
+ xml_to_obj(REXML::XPath.first(root, 'x:Arg', {'x' => obj_ns.uri})),
1272
+ xml_to_obj(REXML::XPath.first(root, 'x:Pattern', {'x' => obj_ns.uri}))
1273
+ )
1274
+ end
1275
+ end
1276
+
1277
+ # The Not Like expression of a query
1278
+ class NotLikePred < LikePred
1279
+ def self.xml_type; 'notLikePredType' end
1280
+
1281
+ def to_s
1282
+ "#{arg} NOT LIKE #{pattern}"
1283
+ end
1284
+ end
1285
+
1286
+ # Represents expressions like (A)
1287
+ class ClosedSearch < Search
1288
+ attr_reader :condition
1289
+
1290
+ def self.xml_type; 'closedSearchType' end
1291
+
1292
+ def initialize(condition)
1293
+ self.condition = condition
1294
+ end
1295
+
1296
+ def condition=(c)
1297
+ raise_argument_required_error('condition') if !c
1298
+ raise_type_mismatch_error(c, Search)
1299
+ @condition = c
1300
+ end
1301
+
1302
+ def ==(s)
1303
+ self.condition == s.condition
1304
+ end
1305
+
1306
+ def to_s
1307
+ "(#{self.condition})"
1308
+ end
1309
+
1310
+ def to_xml(name=nil)
1311
+ el = super(name)
1312
+ el.add_element(self.condition.to_xml('Condition'))
1313
+ collapse_namespaces(el)
1314
+ el
1315
+ end
1316
+
1317
+ def self.from_xml(xml)
1318
+ root = element_from(xml)
1319
+
1320
+ self.new(xml_to_obj(REXML::XPath.first(root, 'x:Condition', {'x' => obj_ns.uri})))
1321
+ end
1322
+ end
1323
+
1324
+ # Represents the Comparison of two expressions
1325
+ class ComparisonPred < Search
1326
+ attr_reader :arg1, :comparison, :arg2
1327
+
1328
+ def self.xml_type; 'comparisonPredType' end
1329
+
1330
+ def initialize(arg1, comparison, arg2)
1331
+ self.arg1 = arg1
1332
+ self.comparison = comparison
1333
+ self.arg2 = arg2
1334
+ end
1335
+
1336
+ def arg1=(a)
1337
+ raise_argument_required_error('argument 1') if !a
1338
+ raise_type_mismatch_error(a, ScalarExpression)
1339
+ @arg1 = a
1340
+ end
1341
+
1342
+ def comparison=(c)
1343
+ raise_argument_required_error('comparison') if !c
1344
+
1345
+ c = Comparison.new(c) if c.is_a?(String)
1346
+ raise_type_mismatch_error(c, Comparison)
1347
+
1348
+ @comparison = c
1349
+ end
1350
+
1351
+ def arg2=(a)
1352
+ raise_argument_required_error('argument 2') if !a
1353
+ raise_type_mismatch_error(a, ScalarExpression)
1354
+ @arg2 = a
1355
+ end
1356
+
1357
+ def ==(p)
1358
+ self.arg1 == p.arg1 and
1359
+ self.comparison == p.comparison and
1360
+ self.arg2 == p.arg2
1361
+ end
1362
+
1363
+ def to_s
1364
+ "#{self.arg1} #{self.comparison} #{self.arg2}"
1365
+ end
1366
+
1367
+ def to_xml(name=nil)
1368
+ el = super(name)
1369
+
1370
+ el.attributes["#{obj_ns.prefix}:Comparison"] = self.comparison.to_s
1371
+ el.add_element(self.arg1.to_xml('Arg'))
1372
+ el.add_element(self.arg2.to_xml('Arg'))
1373
+
1374
+ collapse_namespaces(el)
1375
+ el
1376
+ end
1377
+
1378
+ def self.from_xml(xml)
1379
+ root = element_from(xml)
1380
+
1381
+ args = REXML::XPath.match(root, 'x:Arg', {'x' => obj_ns.uri})
1382
+ self.new(
1383
+ xml_to_obj(args[0]),
1384
+ Comparison.new(root.attributes.get_attribute_ns(obj_ns.uri, 'Comparison').value),
1385
+ xml_to_obj(args[1])
1386
+ )
1387
+ end
1388
+ end
1389
+
1390
+ # Represents the Between expression of a query
1391
+ class BetweenPred < Search
1392
+ attr_reader :arg1, :arg2, :arg3
1393
+
1394
+ def self.xml_type; 'betweenPredType' end
1395
+
1396
+ def initialize(arg1, arg2, arg3)
1397
+ self.arg1 = arg1
1398
+ self.arg2 = arg2
1399
+ self.arg3 = arg3
1400
+ end
1401
+
1402
+ def arg1=(a)
1403
+ raise_argument_required_error('argument 1') if !a
1404
+ raise_type_mismatch_error(a, ScalarExpression)
1405
+ @arg1 = a
1406
+ end
1407
+
1408
+ def arg2=(a)
1409
+ raise_argument_required_error('argument 2') if !a
1410
+ raise_type_mismatch_error(a, ScalarExpression)
1411
+ @arg2 = a
1412
+ end
1413
+
1414
+ def arg3=(a)
1415
+ raise_argument_required_error('argument 3') if !a
1416
+ raise_type_mismatch_error(a, ScalarExpression)
1417
+ @arg3 = a
1418
+ end
1419
+
1420
+ def ==(p)
1421
+ self.arg1 == p.arg1 and
1422
+ self.arg2 == p.arg2 and
1423
+ self.arg3 == p.arg3
1424
+ end
1425
+
1426
+ def to_s
1427
+ "#{self.arg1} BETWEEN #{self.arg2} AND #{self.arg3}"
1428
+ end
1429
+
1430
+ def to_xml(name=nil)
1431
+ el = super(name)
1432
+
1433
+ el.add_element(self.arg1.to_xml('Arg'))
1434
+ el.add_element(self.arg2.to_xml('Arg'))
1435
+ el.add_element(self.arg3.to_xml('Arg'))
1436
+
1437
+ collapse_namespaces(el)
1438
+ el
1439
+ end
1440
+
1441
+ def self.from_xml(xml)
1442
+ root = element_from(xml)
1443
+
1444
+ args = REXML::XPath.match(root, 'x:Arg', {'x' => obj_ns.uri})
1445
+ self.new(
1446
+ xml_to_obj(args[0]),
1447
+ xml_to_obj(args[1]),
1448
+ xml_to_obj(args[2])
1449
+ )
1450
+ end
1451
+ end
1452
+
1453
+ # Represents the Not Between expression of a query
1454
+ class NotBetweenPred < BetweenPred
1455
+ def self.xml_type; 'notBetweenPredType' end
1456
+
1457
+ def to_s
1458
+ "#{self.arg1} NOT BETWEEN #{self.arg2} AND #{self.arg3}"
1459
+ end
1460
+ end
1461
+
1462
+ # Represents expressions like Not A
1463
+ class InverseSearch < Search
1464
+ attr_reader :condition
1465
+
1466
+ def self.xml_type; 'inverseSearchType' end
1467
+
1468
+ def initialize(condition)
1469
+ self.condition = condition
1470
+ end
1471
+
1472
+ def condition=(c)
1473
+ raise_argument_required_error('condition') if !c
1474
+ raise_type_mismatch_error(c, Search)
1475
+ @condition = c
1476
+ end
1477
+
1478
+ def ==(p)
1479
+ self.condition == p.condition
1480
+ end
1481
+
1482
+ def to_s
1483
+ "NOT #{condition}"
1484
+ end
1485
+
1486
+ def to_xml(name=nil)
1487
+ el = super(name)
1488
+ el.add_element(self.condition.to_xml('Condition'))
1489
+ collapse_namespaces(el)
1490
+ el
1491
+ end
1492
+
1493
+ def self.from_xml(xml)
1494
+ root = element_from(xml)
1495
+
1496
+ self.new(xml_to_obj(REXML::XPath.first(root, 'x:Condition', {'x' => obj_ns.uri})))
1497
+ end
1498
+ end
1499
+
1500
+ # Represents the Regions such as circle in Where clause
1501
+ class RegionSearch < Search
1502
+ attr_reader :region
1503
+
1504
+ def self.xml_type; 'regionSearchType' end
1505
+
1506
+ def initialize(region)
1507
+ self.region = region
1508
+ end
1509
+
1510
+ def region=(r)
1511
+ raise_argument_required_error('region') if !r
1512
+ raise_type_mismatch_error(r, RegionType)
1513
+ @region = r
1514
+ end
1515
+
1516
+ def ==(s)
1517
+ self.region == s.region
1518
+ end
1519
+
1520
+ def to_s
1521
+ "REGION(#{self.region})"
1522
+ end
1523
+
1524
+ def to_xml(name=nil)
1525
+ el = super(name)
1526
+
1527
+ reg_ns = obj_ns('VORuby::STC::V1_10::Region')
1528
+ el.add_namespace(reg_ns.prefix, reg_ns.uri)
1529
+
1530
+ reg = el.add_element(self.region.to_xml('Region'))
1531
+
1532
+ raise "unable to determine xsi:type of region #{self.region.inspect}" if !self.region.class.respond_to?(:xml_type)
1533
+ reg.attributes["#{XSI_NAMESPACE.prefix}:type"] = "#{reg_ns.prefix}:#{self.region.class.xml_type}"
1534
+
1535
+ collapse_namespaces(el)
1536
+ el
1537
+ end
1538
+
1539
+ def self.from_xml(xml)
1540
+ root = element_from(xml)
1541
+
1542
+ self.new(
1543
+ xml_to_obj(REXML::XPath.first(root, 'x:Region', {'x' => obj_ns('VORuby::STC::V1_10::Region').uri}))
1544
+ )
1545
+ end
1546
+ end
1547
+
1548
+ # Represents the Having expression part of a query
1549
+ class Having
1550
+ include SerializableToXml
1551
+
1552
+ attr_reader :condition
1553
+
1554
+ def self.xml_type; 'havingType' end
1555
+
1556
+ def initialize(condition)
1557
+ self.condition = condition
1558
+ end
1559
+
1560
+ def condition=(c)
1561
+ raise_argument_required_error('condition') if !c
1562
+ raise_type_mismatch_error(c, Search)
1563
+ @condition = c
1564
+ end
1565
+
1566
+ def ==(h)
1567
+ self.condition == h.condition
1568
+ end
1569
+
1570
+ def to_s
1571
+ "HAVING #{self.condition.to_s}"
1572
+ end
1573
+
1574
+ def to_xml(name=nil)
1575
+ el = element_root(name)
1576
+
1577
+ el.add_element(self.condition.to_xml('Condition'))
1578
+
1579
+ collapse_namespaces(el)
1580
+ el
1581
+ end
1582
+
1583
+ def self.from_xml(xml)
1584
+ root = element_from(xml)
1585
+
1586
+ self.new(
1587
+ xml_to_obj(REXML::XPath.first(root, 'x:Condition', {'x' => obj_ns.uri}))
1588
+ )
1589
+ end
1590
+ end
1591
+
1592
+ # Represents the Group By expression part of a query
1593
+ class GroupBy
1594
+ include SerializableToXml
1595
+
1596
+ class ColumnList < TypedArray
1597
+ def self.restricted_to; [ColumnReference] end
1598
+ def self.minimum_length; 1 end
1599
+ end
1600
+
1601
+ attr_reader :columns
1602
+
1603
+ def self.xml_type; 'groupByType' end
1604
+
1605
+ def initialize(columns)
1606
+ self.columns = columns
1607
+ end
1608
+
1609
+ def columns=(cs)
1610
+ raise_argument_required_error('columns') if !cs
1611
+
1612
+ cs = GroupBy::ColumnList.new(cs) if cs.class == Array
1613
+ raise_type_mismatch_error(cs, GroupBy::ColumnList)
1614
+
1615
+ @columns = cs
1616
+ end
1617
+
1618
+ def ==(g)
1619
+ self.columns == g.columns
1620
+ end
1621
+
1622
+ def to_s
1623
+ "GROUP BY #{self.columns.collect{ |c| c.to_s }.join(', ')}"
1624
+ end
1625
+
1626
+ def to_xml(name=nil)
1627
+ el = element_root(name)
1628
+
1629
+ self.columns.each{ |c| el.add_element(c.to_xml('Column')) }
1630
+
1631
+ collapse_namespaces(el)
1632
+ el
1633
+ end
1634
+
1635
+ def self.from_xml(xml)
1636
+ root = element_from(xml)
1637
+
1638
+ self.new(
1639
+ GroupBy::ColumnList.new(
1640
+ REXML::XPath.match(root, 'x:Column', {'x' => obj_ns.uri}).collect{ |cel| xml_to_obj(cel) }
1641
+ )
1642
+ )
1643
+ end
1644
+ end
1645
+
1646
+ # Represents the Where part of the query
1647
+ class Where
1648
+ include SerializableToXml
1649
+
1650
+ attr_reader :condition
1651
+
1652
+ def self.xml_type; 'whereType' end
1653
+
1654
+ def initialize(condition)
1655
+ self.condition = condition
1656
+ end
1657
+
1658
+ def condition=(c)
1659
+ raise_argument_required_error('condition') if !c
1660
+ raise_type_mismatch_error(c, Search)
1661
+ @condition = c
1662
+ end
1663
+
1664
+ def ==(w)
1665
+ self.condition == w.condition
1666
+ end
1667
+
1668
+ def to_s
1669
+ "WHERE #{self.condition}"
1670
+ end
1671
+
1672
+ def to_xml(name=nil)
1673
+ el = element_root(name)
1674
+
1675
+ el.add_element(self.condition.to_xml('Condition'))
1676
+
1677
+ collapse_namespaces(el)
1678
+ el
1679
+ end
1680
+
1681
+ def self.from_xml(xml)
1682
+ root = element_from(xml)
1683
+
1684
+ self.new(
1685
+ xml_to_obj(REXML::XPath.first(root, 'x:Condition', {'x' => obj_ns.uri}))
1686
+ )
1687
+ end
1688
+ end
1689
+
1690
+ # Represents the From part of the query
1691
+ class From
1692
+ include SerializableToXml
1693
+
1694
+ attr_reader :tables
1695
+
1696
+ def self.xml_type; 'fromType' end
1697
+
1698
+ class TableList < TypedArray
1699
+ def self.restricted_to; [FromTable] end
1700
+ def self.minimum_length; 1 end
1701
+ end
1702
+
1703
+ def initialize(tables)
1704
+ self.tables = tables
1705
+ end
1706
+
1707
+ def tables=(ts)
1708
+ raise_argument_required_error('tables') if !ts
1709
+
1710
+ ts = From::TableList.new(ts) if ts.class == Array
1711
+ raise_type_mismatch_error(ts, From::TableList)
1712
+
1713
+ @tables = ts
1714
+ end
1715
+
1716
+ def ==(f)
1717
+ self.tables == f.tables
1718
+ end
1719
+
1720
+ def to_s
1721
+ "FROM #{self.tables.collect{ |t| t.to_s }.join(', ')}"
1722
+ end
1723
+
1724
+ def to_xml(name=nil)
1725
+ el = element_root(name)
1726
+
1727
+ self.tables.each { |t| el.add_element(t.to_xml('Table')) }
1728
+
1729
+ collapse_namespaces(el)
1730
+ el
1731
+ end
1732
+
1733
+ def self.from_xml(xml)
1734
+ root = element_from(xml)
1735
+
1736
+ self.new(
1737
+ From::TableList.new(
1738
+ REXML::XPath.match(root, 'x:Table', {'x' => obj_ns.uri}).collect{ |tel| xml_to_obj(tel) }
1739
+ )
1740
+ )
1741
+ end
1742
+ end
1743
+
1744
+ # List of items to be selected in the Query
1745
+ class SelectionList
1746
+ include SerializableToXml
1747
+
1748
+ attr_reader :items
1749
+
1750
+ class ItemList < TypedArray
1751
+ def self.restricted_to; [SelectionItem] end
1752
+ def self.minimum_length; 1 end
1753
+ end
1754
+
1755
+ def self.xml_type; 'selectionListType' end
1756
+
1757
+ def initialize(items)
1758
+ self.items = items
1759
+ end
1760
+
1761
+ def items=(is)
1762
+ raise_argument_required_error('items') if !is
1763
+
1764
+ is = SelectionList::ItemList.new(is) if is.class == Array
1765
+ raise_type_mismatch_error(is, SelectionList::ItemList)
1766
+
1767
+ @items = is
1768
+ end
1769
+
1770
+ def ==(l)
1771
+ self.items == l.items
1772
+ end
1773
+
1774
+ def to_s
1775
+ self.items.collect{ |i| i.to_s }.join(', ')
1776
+ end
1777
+
1778
+ def to_xml(name=nil)
1779
+ el = element_root(name)
1780
+
1781
+ self.items.collect{ |i| el.add_element(i.to_xml('Item')) }
1782
+
1783
+ collapse_namespaces(el)
1784
+ el
1785
+ end
1786
+
1787
+ def self.from_xml(xml)
1788
+ root = element_from(xml)
1789
+
1790
+ self.new(
1791
+ SelectionList::ItemList.new(
1792
+ REXML::XPath.match(root, 'x:Item', {'x' => obj_ns.uri}).collect{ |iel| xml_to_obj(iel) }
1793
+ )
1794
+ )
1795
+ end
1796
+ end
1797
+
1798
+ # Represents the TOP part of a query
1799
+ class SelectionLimit
1800
+ include SerializableToXml
1801
+
1802
+ attr_reader :top
1803
+
1804
+ def self.xml_type; 'selectionLimitType' end
1805
+
1806
+ def initialize(top)
1807
+ self.top = top
1808
+ end
1809
+
1810
+ def top=(t)
1811
+ raise_argument_required_error('top') if !t
1812
+ @top = Integer(t)
1813
+ end
1814
+
1815
+ def ==(l)
1816
+ self.top == l.top
1817
+ end
1818
+
1819
+ def to_s
1820
+ "TOP #{self.top}"
1821
+ end
1822
+
1823
+ def to_xml(name=nil)
1824
+ el = element_root(name)
1825
+ el.attributes["#{obj_ns.prefix}:Top"] = self.top.to_s
1826
+ el
1827
+ end
1828
+
1829
+ def self.from_xml(xml)
1830
+ root = element_from(xml)
1831
+ self.new(
1832
+ Integer(
1833
+ root.attributes.get_attribute_ns(obj_ns.uri, 'Top').value
1834
+ )
1835
+ )
1836
+ end
1837
+ end
1838
+
1839
+ # Represents the SQL INTO expression
1840
+ class Into
1841
+ include SerializableToXml
1842
+
1843
+ attr_reader :table_name
1844
+
1845
+ def self.xml_type; 'intoType' end
1846
+
1847
+ def initialize(table_name)
1848
+ self.table_name = table_name
1849
+ end
1850
+
1851
+ def table_name=(n)
1852
+ raise_argument_required_error('table name') if !n
1853
+ @table_name = n.to_s
1854
+ end
1855
+
1856
+ def ==(i)
1857
+ self.table_name == i.table_name
1858
+ end
1859
+
1860
+ def to_s
1861
+ "INTO #{self.table_name}"
1862
+ end
1863
+
1864
+ def to_xml(name=nil)
1865
+ el = element_root(name)
1866
+
1867
+ name = REXML::Element.new("#{obj_ns.prefix}:TableName")
1868
+ name.text = self.table_name
1869
+ el.add_element(name)
1870
+
1871
+ el
1872
+ end
1873
+
1874
+ def self.from_xml(xml)
1875
+ root = element_from(xml)
1876
+
1877
+ self.new(
1878
+ REXML::XPath.first(root, 'x:TableName', {'x' => obj_ns.uri}).text
1879
+ )
1880
+ end
1881
+ end
1882
+
1883
+ # Ascending or Descending order of an Order by term
1884
+ class OrderDirection < Enumeration
1885
+ def self.choices; ['ASC', 'DESC'] end
1886
+ end
1887
+
1888
+ # Option for setting the direction for Order By
1889
+ class OrderOption
1890
+ include SerializableToXml
1891
+
1892
+ attr_reader :direction
1893
+
1894
+ def self.xml_type; 'orderOptionType' end
1895
+
1896
+ def initialize(direction)
1897
+ self.direction = direction
1898
+ end
1899
+
1900
+ def direction=(d)
1901
+ raise_argument_required_error('direction') if !d
1902
+
1903
+ d = OrderDirection.new(d) if d.is_a?(String)
1904
+ raise_type_mismatch_error(d, OrderDirection)
1905
+
1906
+ @direction = d
1907
+ end
1908
+
1909
+ def ==(o)
1910
+ self.direction == o.direction
1911
+ end
1912
+
1913
+ def to_s
1914
+ self.direction.to_s
1915
+ end
1916
+
1917
+ def to_xml(name=nil)
1918
+ el = element_root(name)
1919
+ el.attributes["#{obj_ns.prefix}:Direction"] = self.direction.to_s
1920
+ el
1921
+ end
1922
+
1923
+ def self.from_xml(xml)
1924
+ root = element_from(xml)
1925
+
1926
+ self.new(
1927
+ OrderDirection.new(
1928
+ root.attributes.get_attribute_ns(obj_ns.uri, 'Direction').value
1929
+ )
1930
+ )
1931
+ end
1932
+ end
1933
+
1934
+ # Represents the ORDER BY part of a query
1935
+ class Order
1936
+ include SerializableToXml
1937
+
1938
+ def self.xml_type; 'orderType' end
1939
+
1940
+ attr_reader :expression, :order
1941
+
1942
+ def initialize(expression, order=nil)
1943
+ self.expression = expression
1944
+ self.order = order
1945
+ end
1946
+
1947
+ def expression=(e)
1948
+ raise_argument_required_error('expression') if !e
1949
+ raise_type_mismatch_error(e, ScalarExpression)
1950
+ @expression = e
1951
+ end
1952
+
1953
+ def order=(o)
1954
+ raise_type_mismatch_error(o, OrderOption) if o
1955
+ @order = o
1956
+ end
1957
+
1958
+ def ==(o)
1959
+ self.expression == o.expression and
1960
+ self.order == o.order
1961
+ end
1962
+
1963
+ def to_s
1964
+ s = self.expression.to_s
1965
+ s = "#{s} #{self.order}" if self.order
1966
+ s
1967
+ end
1968
+
1969
+ def to_xml(name=nil)
1970
+ el = element_root(name)
1971
+
1972
+ el.add_element(self.expression.to_xml('Expression'))
1973
+ el.add_element(self.order.to_xml('Order')) if self.order
1974
+
1975
+ collapse_namespaces(el)
1976
+ el
1977
+ end
1978
+
1979
+ def self.from_xml(xml)
1980
+ root = element_from(xml)
1981
+
1982
+ order_el = REXML::XPath.first(root, 'x:Order', {'x' => obj_ns.uri})
1983
+ self.new(
1984
+ xml_to_obj(REXML::XPath.first(root, 'x:Expression', {'x' => obj_ns.uri})),
1985
+ order_el ? xml_to_obj(order_el) : nil
1986
+ )
1987
+ end
1988
+ end
1989
+
1990
+ # List of expressions in which order the results should be provided
1991
+ class OrderExpression
1992
+ include SerializableToXml
1993
+
1994
+ class OrderList < TypedArray
1995
+ def self.restricted_to; [Order] end
1996
+ def self.minimum_length; 1 end
1997
+ end
1998
+
1999
+ attr_reader :items
2000
+
2001
+ def self.xml_type; 'orderExpressionType' end
2002
+
2003
+ def initialize(items)
2004
+ self.items = items
2005
+ end
2006
+
2007
+ def items=(is)
2008
+ raise_argument_required_error('items') if !is
2009
+
2010
+ is = OrderExpression::OrderList.new(is) if is.class == Array
2011
+ raise_type_mismatch_error(is, OrderExpression::OrderList)
2012
+
2013
+ @items = is
2014
+ end
2015
+
2016
+ def ==(e)
2017
+ self.items == e.items
2018
+ end
2019
+
2020
+ def to_s
2021
+ "ORDER BY #{self.items.collect{ |i| i.to_s }.join(', ')}"
2022
+ end
2023
+
2024
+ def to_xml(name=nil)
2025
+ el = element_root(name)
2026
+
2027
+ self.items.collect{ |i| el.add_element(i.to_xml('Item')) }
2028
+
2029
+ collapse_namespaces(el)
2030
+ el
2031
+ end
2032
+
2033
+ def self.from_xml(xml)
2034
+ root = element_from(xml)
2035
+
2036
+ self.new(
2037
+ OrderExpression::OrderList.new(
2038
+ REXML::XPath.match(root, 'x:Item', {'x' => obj_ns.uri}).collect{ |iel| xml_to_obj(iel) }
2039
+ )
2040
+ )
2041
+ end
2042
+ end
2043
+
2044
+ # The base type for selection set in a SQL IN expression
2045
+ class InclusionSet
2046
+ include SerializableToXml
2047
+
2048
+ def to_xml(name=nil)
2049
+ element_root(name)
2050
+ end
2051
+ end
2052
+
2053
+ # Represents a list of constants provided for a SQL IN expression
2054
+ class ConstantListSet < InclusionSet
2055
+ class LiteralList < TypedArray
2056
+ def self.restricted_to; [Literal] end
2057
+ def self.minimum_length; 1 end
2058
+ end
2059
+
2060
+ attr_reader :items
2061
+
2062
+ def self.xml_type; 'ConstantListSet' end
2063
+
2064
+ def initialize(items)
2065
+ self.items = items
2066
+ end
2067
+
2068
+ def items=(is)
2069
+ raise_argument_required_error('items') if !is
2070
+
2071
+ is = ConstantListSet::LiteralList.new(is) if is.class == Array
2072
+ raise_type_mismatch_error(is, ConstantListSet::LiteralList)
2073
+
2074
+ @items = is
2075
+ end
2076
+
2077
+ def ==(s)
2078
+ self.items == s.items
2079
+ end
2080
+
2081
+ def to_s
2082
+ "(#{self.items.collect{ |i| i.to_s }.join(', ')})"
2083
+ end
2084
+
2085
+ def to_xml(name=nil)
2086
+ el = super(name)
2087
+
2088
+ self.items.each{ |i| el.add_element(i.to_xml('Item')) }
2089
+
2090
+ collapse_namespaces(el)
2091
+ el
2092
+ end
2093
+
2094
+ def self.from_xml(xml)
2095
+ root = element_from(xml)
2096
+
2097
+ self.new(
2098
+ ConstantListSet::LiteralList.new(
2099
+ REXML::XPath.match(root, 'x:Item', {'x' => obj_ns.uri}).collect{ |iel| xml_to_obj(iel) }
2100
+ )
2101
+ )
2102
+ end
2103
+ end
2104
+
2105
+ # Represents the subquery in a SQL IN expression
2106
+ class SubQuerySet < InclusionSet
2107
+ attr_reader :selection
2108
+
2109
+ def self.xml_type; 'subQuerySet' end
2110
+
2111
+ def initialize(selection)
2112
+ self.selection = selection
2113
+ end
2114
+
2115
+ def selection=(s)
2116
+ raise_argument_required_error('selection') if !s
2117
+ raise_type_mismatch_error(s, Select)
2118
+ @selection = s
2119
+ end
2120
+
2121
+ def ==(s)
2122
+ self.selection == s.selection
2123
+ end
2124
+
2125
+ def to_s
2126
+ "(#{self.selection})"
2127
+ end
2128
+
2129
+ def to_xml(name=nil)
2130
+ el = super(name)
2131
+
2132
+ el.add_element(self.selection.to_xml('selection'))
2133
+
2134
+ collapse_namespaces(el)
2135
+ el
2136
+ end
2137
+
2138
+ def self.from_xml(xml)
2139
+ root = element_from(xml)
2140
+
2141
+ self.new(xml_to_obj(REXML::XPath.first(root, 'x:selection', {'x' => obj_ns.uri})))
2142
+ end
2143
+ end
2144
+
2145
+ # Represents SQL IN expression
2146
+ class InclusiveSearch < Search
2147
+ attr_reader :expression, :set
2148
+
2149
+ def self.xml_type; 'inclusiveSearchType' end
2150
+
2151
+ def initialize(expression, set)
2152
+ self.expression = expression
2153
+ self.set = set
2154
+ end
2155
+
2156
+ def expression=(e)
2157
+ raise_argument_required_error('expression') if !e
2158
+ raise_type_mismatch_error(e, ScalarExpression)
2159
+ @expression = e
2160
+ end
2161
+
2162
+ def set=(s)
2163
+ raise_argument_required_error('set') if !s
2164
+ raise_type_mismatch_error(s, InclusionSet)
2165
+ @set = s
2166
+ end
2167
+
2168
+ def ==(s)
2169
+ self.expression == s.expression and
2170
+ self.set == s.set
2171
+ end
2172
+
2173
+ def to_s
2174
+ "#{self.expression} IN #{self.set}"
2175
+ end
2176
+
2177
+ def to_xml(name=nil)
2178
+ el = super(name)
2179
+
2180
+ el.add_element(self.expression.to_xml('Expression'))
2181
+ el.add_element(self.set.to_xml('Set'))
2182
+
2183
+ collapse_namespaces(el)
2184
+ el
2185
+ end
2186
+
2187
+ def self.from_xml(xml)
2188
+ root = element_from(xml)
2189
+
2190
+ self.new(
2191
+ xml_to_obj(REXML::XPath.first(root, 'x:Expression', {'x' => obj_ns.uri})),
2192
+ xml_to_obj(REXML::XPath.first(root, 'x:Set', {'x' => obj_ns.uri}))
2193
+ )
2194
+ end
2195
+ end
2196
+
2197
+ # Represents SQL NOT IN expression
2198
+ class ExclusiveSearch < Search
2199
+ attr_reader :expression, :set
2200
+
2201
+ def self.xml_type; 'exclusiveSearchType' end
2202
+
2203
+ def initialize(expression, set)
2204
+ self.expression = expression
2205
+ self.set = set
2206
+ end
2207
+
2208
+ def expression=(e)
2209
+ raise_argument_required_error('expression') if !e
2210
+ raise_type_mismatch_error(e, ScalarExpression)
2211
+ @expression = e
2212
+ end
2213
+
2214
+ def set=(s)
2215
+ raise_argument_required_error('set') if !s
2216
+ raise_type_mismatch_error(s, InclusionSet)
2217
+ @set = s
2218
+ end
2219
+
2220
+ def ==(s)
2221
+ self.expression == s.expression and
2222
+ self.set == s.set
2223
+ end
2224
+
2225
+ def to_s
2226
+ "#{expression} NOT IN #{set}"
2227
+ end
2228
+
2229
+ def to_xml(name=nil)
2230
+ el = super(name)
2231
+
2232
+ el.add_element(self.expression.to_xml('Expression'))
2233
+ el.add_element(self.set.to_xml('Set'))
2234
+
2235
+ collapse_namespaces(el)
2236
+ el
2237
+ end
2238
+
2239
+ def self.from_xml(xml)
2240
+ root = element_from(xml)
2241
+
2242
+ self.new(
2243
+ xml_to_obj(REXML::XPath.first(root, 'x:Expression', {'x' => obj_ns.uri})),
2244
+ xml_to_obj(REXML::XPath.first(root, 'x:Set', {'x' => obj_ns.uri}))
2245
+ )
2246
+ end
2247
+ end
2248
+
2249
+ # The SELECT part of a query
2250
+ class Select
2251
+ include SerializableToXml
2252
+
2253
+ attr_reader :allow, :restrict, :selection_list, :into,
2254
+ :from, :where, :group_by, :having, :order_by, :start_comment, :end_comment
2255
+
2256
+ def self.xml_type; 'selectType' end
2257
+
2258
+ def initialize(selection_list, options={})
2259
+ options.each { |key, value| send("#{key}=", value) }
2260
+ self.selection_list = selection_list
2261
+ end
2262
+
2263
+ def allow=(a)
2264
+ raise_type_mismatch_error(a, SelectionOption) if a
2265
+ @allow = a
2266
+ end
2267
+
2268
+ def restrict=(r)
2269
+ raise_type_mismatch_error(r, SelectionLimit) if r
2270
+ @restrict = r
2271
+ end
2272
+
2273
+ def selection_list=(l)
2274
+ raise_argument_required_error('selection list') if !l
2275
+ raise_type_mismatch_error(l, SelectionList)
2276
+ @selection_list = l
2277
+ end
2278
+
2279
+ def into=(i)
2280
+ raise_type_mismatch_error(i, Into) if i
2281
+ @into = i
2282
+ end
2283
+
2284
+ def from=(f)
2285
+ raise_type_mismatch_error(f, From) if f
2286
+ @from = f
2287
+ end
2288
+
2289
+ def where=(w)
2290
+ raise_type_mismatch_error(w, Where) if w
2291
+ @where = w
2292
+ end
2293
+
2294
+ def group_by=(g)
2295
+ raise_type_mismatch_error(g, GroupBy) if g
2296
+ @group_by = g
2297
+ end
2298
+
2299
+ def having=(h)
2300
+ raise_type_mismatch_error(h, Having) if h
2301
+ @having = h
2302
+ end
2303
+
2304
+ def order_by=(o)
2305
+ raise_type_mismatch_error(o, OrderExpression) if o
2306
+ @order_by = o
2307
+ end
2308
+
2309
+ def start_comment=(c)
2310
+ @start_comment = c ? c.to_s : nil
2311
+ end
2312
+
2313
+ def end_comment=(c)
2314
+ @end_comment = c ? c.to_s : nil
2315
+ end
2316
+
2317
+ def ==(s)
2318
+ self.allow == s.allow and
2319
+ self.restrict == s.restrict and
2320
+ self.selection_list == s.selection_list and
2321
+ self.into == s.into and
2322
+ self.from == s.from and
2323
+ self.where == s.where and
2324
+ self.group_by == s.group_by and
2325
+ self.having == s.having and
2326
+ self.order_by == s.order_by and
2327
+ self.start_comment == s.start_comment and
2328
+ self.end_comment == s.end_comment
2329
+ end
2330
+
2331
+ def to_s
2332
+ s = 'SELECT'
2333
+ s << " #{self.allow}" if self.allow
2334
+ s << " #{self.restrict}" if self.restrict
2335
+ s << " #{self.selection_list}"
2336
+ s << " #{self.into}" if self.into
2337
+ s << " #{self.from}" if self.from
2338
+ s << " #{self.where}" if self.where
2339
+ s << " #{self.group_by}" if self.group_by
2340
+ s << " #{self.having}" if self.having
2341
+ s << " #{self.order_by}" if self.order_by
2342
+ s
2343
+ end
2344
+
2345
+ def to_xml(name='Select')
2346
+ el = element_root(name)
2347
+
2348
+ el.add_element(self.allow.to_xml('Allow')) if self.allow
2349
+ el.add_element(self.restrict.to_xml('Restrict')) if self.restrict
2350
+ el.add_element(self.selection_list.to_xml('SelectionList'))
2351
+ el.add_element(self.into.to_xml('InTo')) if self.into
2352
+ el.add_element(self.from.to_xml('From')) if self.from
2353
+ el.add_element(self.where.to_xml('Where')) if self.where
2354
+ el.add_element(self.group_by.to_xml('GroupBy')) if self.group_by
2355
+ el.add_element(self.having.to_xml('Having')) if self.having
2356
+ el.add_element(self.order_by.to_xml('OrderBy')) if self.order_by
2357
+
2358
+ if self.start_comment
2359
+ sc = REXML::Element.new("#{obj_ns.prefix}:StartComment")
2360
+ sc.text = self.start_comment
2361
+ el.add_element(sc)
2362
+ end
2363
+
2364
+ if self.end_comment
2365
+ ec = REXML::Element.new("#{obj_ns.prefix}:EndComment")
2366
+ ec.text = self.end_comment
2367
+ el.add_element(ec)
2368
+ end
2369
+
2370
+ collapse_namespaces(el)
2371
+ el
2372
+ end
2373
+
2374
+ def self.from_xml(xml)
2375
+ root = element_from(xml)
2376
+
2377
+ options = {}
2378
+
2379
+ allow = REXML::XPath.first(root, 'x:Allow', {'x' => obj_ns.uri})
2380
+ options[:allow] = xml_to_obj(allow) if allow
2381
+
2382
+ restrict = REXML::XPath.first(root, 'x:Restrict', {'x' => obj_ns.uri})
2383
+ options[:restrict] = xml_to_obj(restrict) if restrict
2384
+
2385
+ into = REXML::XPath.first(root, 'x:InTo', {'x' => obj_ns.uri})
2386
+ options[:into] = xml_to_obj(into) if into
2387
+
2388
+ from = REXML::XPath.first(root, 'x:From', {'x' => obj_ns.uri})
2389
+ options[:from] = xml_to_obj(from) if from
2390
+
2391
+ where = REXML::XPath.first(root, 'x:Where', {'x' => obj_ns.uri})
2392
+ options[:where] = xml_to_obj(where) if where
2393
+
2394
+ group_by = REXML::XPath.first(root, 'x:GroupBy', {'x' => obj_ns.uri})
2395
+ options[:group_by] = xml_to_obj(group_by) if group_by
2396
+
2397
+ having = REXML::XPath.first(root, 'x:Having', {'x' => obj_ns.uri})
2398
+ options[:having] = xml_to_obj(having) if having
2399
+
2400
+ order_by = REXML::XPath.first(root, 'x:OrderBy', {'x' => obj_ns.uri})
2401
+ options[:order_by] = xml_to_obj(order_by) if order_by
2402
+
2403
+ start_comment = REXML::XPath.first(root, 'x:StartComment', {'x' => obj_ns.uri})
2404
+ options[:start_comment] = start_comment.text if start_comment
2405
+
2406
+ end_comment = REXML::XPath.first(root, 'x:EndComment', {'x' => obj_ns.uri})
2407
+ options[:end_comment] = end_comment.text if end_comment
2408
+
2409
+ self.new(
2410
+ xml_to_obj(REXML::XPath.first(root, 'x:SelectionList', {'x' => obj_ns.uri})),
2411
+ options
2412
+ )
2413
+ end
2414
+ end
2415
+
2416
+ end
2417
+ end
2418
+ end