quickbooks 0.4.0 → 0.9.9

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 (293) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +23 -0
  3. data/License.txt +54 -0
  4. data/Manifest.txt +73 -0
  5. data/README.txt +79 -0
  6. data/Rakefile +17 -78
  7. data/lib/quickbooks.rb +153 -7
  8. data/lib/quickbooks/adaptability.rb +67 -0
  9. data/lib/quickbooks/adapters/http_adapter.rb +94 -0
  10. data/lib/quickbooks/adapters/https_adapter.rb +57 -0
  11. data/lib/quickbooks/adapters/ole_adapter.rb +141 -110
  12. data/lib/quickbooks/adapters/spew_adapter.rb +39 -0
  13. data/lib/quickbooks/adapters/tcp_adapter.rb +71 -0
  14. data/lib/quickbooks/adapters/test_adapter.rb +62 -0
  15. data/lib/quickbooks/element.rb +385 -0
  16. data/lib/quickbooks/element_collection.rb +105 -0
  17. data/lib/quickbooks/extlib.rb +8 -0
  18. data/lib/quickbooks/extlib/assertions.rb +8 -0
  19. data/lib/quickbooks/extlib/class.rb +98 -0
  20. data/lib/quickbooks/extlib/days_and_times.rb +10 -0
  21. data/lib/quickbooks/extlib/days_and_times/duration.rb +362 -0
  22. data/lib/quickbooks/extlib/days_and_times/numeric.rb +48 -0
  23. data/lib/quickbooks/extlib/days_and_times/object.rb +19 -0
  24. data/lib/quickbooks/extlib/days_and_times/time.rb +137 -0
  25. data/lib/quickbooks/extlib/hash.rb +327 -0
  26. data/lib/quickbooks/extlib/hook.rb +366 -0
  27. data/lib/quickbooks/extlib/inflection.rb +436 -0
  28. data/lib/quickbooks/extlib/logger.rb +202 -0
  29. data/lib/quickbooks/extlib/object.rb +162 -0
  30. data/lib/quickbooks/extlib/pathname.rb +15 -0
  31. data/lib/quickbooks/extlib/rubygems.rb +38 -0
  32. data/lib/quickbooks/extlib/string.rb +32 -0
  33. data/lib/quickbooks/extlib/time.rb +41 -0
  34. data/lib/quickbooks/model.rb +503 -121
  35. data/lib/quickbooks/option.rb +95 -0
  36. data/lib/quickbooks/property.rb +69 -0
  37. data/lib/quickbooks/ruby_ext.rb +251 -0
  38. data/lib/quickbooks/type.rb +75 -0
  39. data/lib/quickbooks/types.rb +58 -0
  40. data/lib/quickbooks/version.rb +10 -0
  41. data/lib/quickbooks/xsd.rb +243 -0
  42. data/lib/quickbooks/xsd/attribute.rb +57 -0
  43. data/lib/quickbooks/xsd/choice.rb +94 -0
  44. data/lib/quickbooks/xsd/complex_type.rb +77 -0
  45. data/lib/quickbooks/xsd/element.rb +214 -0
  46. data/lib/quickbooks/xsd/group.rb +94 -0
  47. data/lib/quickbooks/xsd/restriction.rb +51 -0
  48. data/lib/quickbooks/xsd/sequence.rb +85 -0
  49. data/lib/quickbooks/xsd/simple_type.rb +87 -0
  50. data/lib/quickbooks/xsd/union.rb +70 -0
  51. data/lib/quickbooks/xsd/validation.rb +89 -0
  52. data/lib/quickbooks/xsd/xml_parse.rb +80 -0
  53. data/quickbooks.gemspec +36 -0
  54. data/source/qbxml21_demo.xsd +2223 -0
  55. data/source/qbxmlops_demo.xsd +483 -0
  56. data/source/qbxmltypes.xsd +160 -0
  57. data/spec/association_spec.rb +5 -0
  58. data/spec/element_collection_spec.rb +8 -0
  59. data/spec/find_spec.rb +30 -0
  60. data/spec/lib/quickbooks/element_spec.rb +83 -0
  61. data/spec/lib/quickbooks/elements/sales_order_add_spec.rb +14 -0
  62. data/spec/lib/quickbooks/elements/vendor_add_spec.rb +78 -0
  63. data/spec/lib/quickbooks/model_spec.rb +89 -0
  64. data/spec/lib/quickbooks/models/customer_spec.rb +52 -0
  65. data/spec/lib/quickbooks/models/invoice_spec.rb +12 -0
  66. data/spec/lib/quickbooks/models/sales_order_line_spec.rb +0 -0
  67. data/spec/lib/quickbooks/models/sales_order_spec.rb +145 -0
  68. data/spec/lib/quickbooks/xsd/choice_spec.rb +18 -0
  69. data/spec/pending_spec.rb +11 -0
  70. data/spec/quickbooks_spec.rb +38 -0
  71. data/spec/repeatable_spec.rb +20 -0
  72. data/spec/requires_spec.rb +10 -0
  73. data/spec/spec_helper.rb +5 -0
  74. data/spec/validation_spec.rb +24 -0
  75. metadata +133 -285
  76. metadata.gz.sig +0 -0
  77. data/LICENSE +0 -16
  78. data/README +0 -49
  79. data/doc/classes/Array.html +0 -368
  80. data/doc/classes/Array.src/M000026.html +0 -18
  81. data/doc/classes/Array.src/M000027.html +0 -21
  82. data/doc/classes/Array.src/M000028.html +0 -18
  83. data/doc/classes/Array.src/M000029.html +0 -19
  84. data/doc/classes/Array.src/M000030.html +0 -18
  85. data/doc/classes/Array.src/M000031.html +0 -23
  86. data/doc/classes/Array.src/M000032.html +0 -18
  87. data/doc/classes/Array.src/M000033.html +0 -18
  88. data/doc/classes/Array.src/M000034.html +0 -18
  89. data/doc/classes/Array.src/M000035.html +0 -19
  90. data/doc/classes/Array.src/M000036.html +0 -18
  91. data/doc/classes/Array.src/M000037.html +0 -23
  92. data/doc/classes/Array.src/M000038.html +0 -18
  93. data/doc/classes/Array.src/M000039.html +0 -21
  94. data/doc/classes/Array.src/M000040.html +0 -18
  95. data/doc/classes/Array.src/M000041.html +0 -18
  96. data/doc/classes/Class.html +0 -171
  97. data/doc/classes/Class.src/M000042.html +0 -18
  98. data/doc/classes/Class.src/M000043.html +0 -18
  99. data/doc/classes/Hash.html +0 -516
  100. data/doc/classes/Hash.src/M000001.html +0 -18
  101. data/doc/classes/Hash.src/M000002.html +0 -21
  102. data/doc/classes/Hash.src/M000003.html +0 -18
  103. data/doc/classes/Hash.src/M000004.html +0 -21
  104. data/doc/classes/Hash.src/M000005.html +0 -18
  105. data/doc/classes/Hash.src/M000006.html +0 -20
  106. data/doc/classes/Hash.src/M000007.html +0 -18
  107. data/doc/classes/Hash.src/M000008.html +0 -22
  108. data/doc/classes/Hash.src/M000009.html +0 -18
  109. data/doc/classes/Hash.src/M000010.html +0 -21
  110. data/doc/classes/Hash.src/M000011.html +0 -24
  111. data/doc/classes/Hash.src/M000012.html +0 -18
  112. data/doc/classes/Hash.src/M000013.html +0 -21
  113. data/doc/classes/Hash.src/M000014.html +0 -18
  114. data/doc/classes/Hash.src/M000015.html +0 -21
  115. data/doc/classes/Hash.src/M000016.html +0 -18
  116. data/doc/classes/Hash.src/M000017.html +0 -21
  117. data/doc/classes/Hash.src/M000018.html +0 -27
  118. data/doc/classes/Hash.src/M000019.html +0 -20
  119. data/doc/classes/Hash.src/M000020.html +0 -18
  120. data/doc/classes/Hash.src/M000021.html +0 -18
  121. data/doc/classes/Hash.src/M000022.html +0 -18
  122. data/doc/classes/Hash.src/M000023.html +0 -18
  123. data/doc/classes/Hash.src/M000024.html +0 -18
  124. data/doc/classes/Hash.src/M000025.html +0 -28
  125. data/doc/classes/Object.html +0 -278
  126. data/doc/classes/Object.src/M000044.html +0 -24
  127. data/doc/classes/Object.src/M000045.html +0 -19
  128. data/doc/classes/Object.src/M000046.html +0 -24
  129. data/doc/classes/Object.src/M000047.html +0 -18
  130. data/doc/classes/Object.src/M000048.html +0 -19
  131. data/doc/classes/Object.src/M000049.html +0 -18
  132. data/doc/classes/Object.src/M000050.html +0 -18
  133. data/doc/classes/Object.src/M000051.html +0 -18
  134. data/doc/classes/Qbxml.html +0 -131
  135. data/doc/classes/Qbxml/Request.html +0 -224
  136. data/doc/classes/Qbxml/Request.src/M000132.html +0 -66
  137. data/doc/classes/Qbxml/Request.src/M000133.html +0 -19
  138. data/doc/classes/Qbxml/Request.src/M000134.html +0 -83
  139. data/doc/classes/Qbxml/RequestSet.html +0 -199
  140. data/doc/classes/Qbxml/RequestSet.src/M000135.html +0 -22
  141. data/doc/classes/Qbxml/RequestSet.src/M000136.html +0 -26
  142. data/doc/classes/Qbxml/RequestSet.src/M000137.html +0 -18
  143. data/doc/classes/Qbxml/RequestSet.src/M000138.html +0 -22
  144. data/doc/classes/Qbxml/Response.html +0 -302
  145. data/doc/classes/Qbxml/Response.src/M000123.html +0 -24
  146. data/doc/classes/Qbxml/Response.src/M000124.html +0 -19
  147. data/doc/classes/Qbxml/Response.src/M000125.html +0 -55
  148. data/doc/classes/Qbxml/Response.src/M000126.html +0 -18
  149. data/doc/classes/Qbxml/Response.src/M000127.html +0 -18
  150. data/doc/classes/Qbxml/Response.src/M000128.html +0 -18
  151. data/doc/classes/Qbxml/Response.src/M000129.html +0 -18
  152. data/doc/classes/Qbxml/Response.src/M000130.html +0 -18
  153. data/doc/classes/Qbxml/Response.src/M000131.html +0 -63
  154. data/doc/classes/Qbxml/ResponseSet.html +0 -244
  155. data/doc/classes/Qbxml/ResponseSet.src/M000116.html +0 -22
  156. data/doc/classes/Qbxml/ResponseSet.src/M000117.html +0 -26
  157. data/doc/classes/Qbxml/ResponseSet.src/M000118.html +0 -24
  158. data/doc/classes/Qbxml/ResponseSet.src/M000119.html +0 -20
  159. data/doc/classes/Qbxml/ResponseSet.src/M000120.html +0 -27
  160. data/doc/classes/Qbxml/ResponseSet.src/M000121.html +0 -18
  161. data/doc/classes/Qbxml/ResponseSet.src/M000122.html +0 -18
  162. data/doc/classes/Quickbooks.html +0 -196
  163. data/doc/classes/Quickbooks/Address.html +0 -139
  164. data/doc/classes/Quickbooks/Address.src/M000115.html +0 -19
  165. data/doc/classes/Quickbooks/Base.html +0 -567
  166. data/doc/classes/Quickbooks/Base.src/M000095.html +0 -18
  167. data/doc/classes/Quickbooks/Base.src/M000096.html +0 -20
  168. data/doc/classes/Quickbooks/Base.src/M000097.html +0 -19
  169. data/doc/classes/Quickbooks/Base.src/M000098.html +0 -18
  170. data/doc/classes/Quickbooks/Base.src/M000099.html +0 -19
  171. data/doc/classes/Quickbooks/Base.src/M000100.html +0 -30
  172. data/doc/classes/Quickbooks/Base.src/M000101.html +0 -22
  173. data/doc/classes/Quickbooks/Base.src/M000102.html +0 -30
  174. data/doc/classes/Quickbooks/Base.src/M000103.html +0 -19
  175. data/doc/classes/Quickbooks/Base.src/M000104.html +0 -19
  176. data/doc/classes/Quickbooks/Base.src/M000105.html +0 -18
  177. data/doc/classes/Quickbooks/Base.src/M000106.html +0 -18
  178. data/doc/classes/Quickbooks/Base.src/M000107.html +0 -19
  179. data/doc/classes/Quickbooks/Base.src/M000108.html +0 -18
  180. data/doc/classes/Quickbooks/Base.src/M000109.html +0 -45
  181. data/doc/classes/Quickbooks/Base.src/M000110.html +0 -18
  182. data/doc/classes/Quickbooks/Base.src/M000111.html +0 -18
  183. data/doc/classes/Quickbooks/Base.src/M000112.html +0 -20
  184. data/doc/classes/Quickbooks/BillAddress.html +0 -113
  185. data/doc/classes/Quickbooks/CreditCardInfo.html +0 -113
  186. data/doc/classes/Quickbooks/Customer.html +0 -113
  187. data/doc/classes/Quickbooks/CustomerTypeRef.html +0 -113
  188. data/doc/classes/Quickbooks/Deleted.html +0 -113
  189. data/doc/classes/Quickbooks/ItemSalesTaxRef.html +0 -113
  190. data/doc/classes/Quickbooks/JobTypeRef.html +0 -113
  191. data/doc/classes/Quickbooks/ListDeleted.html +0 -139
  192. data/doc/classes/Quickbooks/ListDeleted.src/M000114.html +0 -18
  193. data/doc/classes/Quickbooks/ListItem.html +0 -170
  194. data/doc/classes/Quickbooks/ListItem.src/M000093.html +0 -20
  195. data/doc/classes/Quickbooks/ListItem.src/M000094.html +0 -18
  196. data/doc/classes/Quickbooks/Model.html +0 -462
  197. data/doc/classes/Quickbooks/Model.src/M000073.html +0 -24
  198. data/doc/classes/Quickbooks/Model.src/M000074.html +0 -19
  199. data/doc/classes/Quickbooks/Model.src/M000075.html +0 -18
  200. data/doc/classes/Quickbooks/Model.src/M000076.html +0 -18
  201. data/doc/classes/Quickbooks/Model.src/M000077.html +0 -18
  202. data/doc/classes/Quickbooks/Model.src/M000078.html +0 -22
  203. data/doc/classes/Quickbooks/Model.src/M000079.html +0 -32
  204. data/doc/classes/Quickbooks/Model.src/M000080.html +0 -32
  205. data/doc/classes/Quickbooks/Model.src/M000081.html +0 -18
  206. data/doc/classes/Quickbooks/Model.src/M000082.html +0 -18
  207. data/doc/classes/Quickbooks/Model.src/M000083.html +0 -22
  208. data/doc/classes/Quickbooks/Model.src/M000084.html +0 -23
  209. data/doc/classes/Quickbooks/Model.src/M000085.html +0 -18
  210. data/doc/classes/Quickbooks/Model.src/M000086.html +0 -21
  211. data/doc/classes/Quickbooks/Model.src/M000087.html +0 -26
  212. data/doc/classes/Quickbooks/Model.src/M000088.html +0 -26
  213. data/doc/classes/Quickbooks/Model.src/M000089.html +0 -26
  214. data/doc/classes/Quickbooks/Model.src/M000090.html +0 -21
  215. data/doc/classes/Quickbooks/Model.src/M000091.html +0 -23
  216. data/doc/classes/Quickbooks/OleAdapter.html +0 -129
  217. data/doc/classes/Quickbooks/OleAdapter/Connection.html +0 -343
  218. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000058.html +0 -18
  219. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000059.html +0 -19
  220. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000060.html +0 -24
  221. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000061.html +0 -18
  222. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000062.html +0 -18
  223. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000063.html +0 -21
  224. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000064.html +0 -24
  225. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000065.html +0 -20
  226. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000066.html +0 -24
  227. data/doc/classes/Quickbooks/OleAdapter/Connection.src/M000067.html +0 -24
  228. data/doc/classes/Quickbooks/OleAdapter/Ole.html +0 -209
  229. data/doc/classes/Quickbooks/OleAdapter/Ole.src/M000068.html +0 -21
  230. data/doc/classes/Quickbooks/OleAdapter/Ole.src/M000069.html +0 -22
  231. data/doc/classes/Quickbooks/OleAdapter/Ole.src/M000070.html +0 -18
  232. data/doc/classes/Quickbooks/ParentRef.html +0 -113
  233. data/doc/classes/Quickbooks/PreferredPaymentMethodRef.html +0 -113
  234. data/doc/classes/Quickbooks/PriceLevelRef.html +0 -113
  235. data/doc/classes/Quickbooks/QbxmlDebugAdapter.html +0 -111
  236. data/doc/classes/Quickbooks/QbxmlDebugAdapter/Connection.html +0 -139
  237. data/doc/classes/Quickbooks/QbxmlDebugAdapter/Connection.src/M000057.html +0 -18
  238. data/doc/classes/Quickbooks/Ref.html +0 -146
  239. data/doc/classes/Quickbooks/Ref.src/M000113.html +0 -18
  240. data/doc/classes/Quickbooks/SalesRepRef.html +0 -113
  241. data/doc/classes/Quickbooks/SalesTaxCodeRef.html +0 -113
  242. data/doc/classes/Quickbooks/ShipAddress.html +0 -113
  243. data/doc/classes/Quickbooks/TermsRef.html +0 -113
  244. data/doc/classes/Quickbooks/Transaction.html +0 -154
  245. data/doc/classes/Quickbooks/Transaction.src/M000071.html +0 -19
  246. data/doc/classes/Quickbooks/Transaction.src/M000072.html +0 -18
  247. data/doc/classes/Quickbooks/TxnDeleted.html +0 -139
  248. data/doc/classes/Quickbooks/TxnDeleted.src/M000092.html +0 -18
  249. data/doc/classes/String.html +0 -203
  250. data/doc/classes/String.src/M000052.html +0 -18
  251. data/doc/classes/String.src/M000053.html +0 -18
  252. data/doc/classes/String.src/M000054.html +0 -18
  253. data/doc/classes/String.src/M000055.html +0 -18
  254. data/doc/classes/String.src/M000056.html +0 -18
  255. data/doc/created.rid +0 -1
  256. data/doc/files/LICENSE.html +0 -129
  257. data/doc/files/README.html +0 -225
  258. data/doc/files/lib/qbxml/request_rb.html +0 -110
  259. data/doc/files/lib/qbxml/response_rb.html +0 -109
  260. data/doc/files/lib/qbxml/support_rb.html +0 -101
  261. data/doc/files/lib/qbxml_rb.html +0 -122
  262. data/doc/files/lib/quickbooks/adapters/ole_adapter_rb.html +0 -108
  263. data/doc/files/lib/quickbooks/adapters/qbxml_debug_adapter_rb.html +0 -108
  264. data/doc/files/lib/quickbooks/base_rb.html +0 -327
  265. data/doc/files/lib/quickbooks/model_rb.html +0 -108
  266. data/doc/files/lib/quickbooks/models/common/address_rb.html +0 -101
  267. data/doc/files/lib/quickbooks/models/common/all_refs_rb.html +0 -101
  268. data/doc/files/lib/quickbooks/models/customer/credit_card_info_rb.html +0 -101
  269. data/doc/files/lib/quickbooks/models/customer_rb.html +0 -110
  270. data/doc/files/lib/quickbooks/models/deleted_rb.html +0 -101
  271. data/doc/files/lib/quickbooks/models/list_item_rb.html +0 -101
  272. data/doc/files/lib/quickbooks/models/transaction_rb.html +0 -101
  273. data/doc/files/lib/quickbooks/ruby_magic_rb.html +0 -120
  274. data/doc/files/lib/quickbooks_rb.html +0 -125
  275. data/doc/fr_class_index.html +0 -64
  276. data/doc/fr_file_index.html +0 -45
  277. data/doc/fr_method_index.html +0 -164
  278. data/doc/index.html +0 -24
  279. data/doc/rdoc-style.css +0 -208
  280. data/lib/qbxml.rb +0 -3
  281. data/lib/qbxml/request.rb +0 -207
  282. data/lib/qbxml/response.rb +0 -197
  283. data/lib/qbxml/support.rb +0 -130
  284. data/lib/quickbooks/adapters/qbxml_debug_adapter.rb +0 -10
  285. data/lib/quickbooks/base.rb +0 -277
  286. data/lib/quickbooks/models/common/address.rb +0 -14
  287. data/lib/quickbooks/models/common/all_refs.rb +0 -37
  288. data/lib/quickbooks/models/customer.rb +0 -70
  289. data/lib/quickbooks/models/customer/credit_card_info.rb +0 -5
  290. data/lib/quickbooks/models/deleted.rb +0 -22
  291. data/lib/quickbooks/models/list_item.rb +0 -41
  292. data/lib/quickbooks/models/transaction.rb +0 -49
  293. data/lib/quickbooks/ruby_magic.rb +0 -213
@@ -0,0 +1,58 @@
1
+ require 'quickbooks/type'
2
+ module Quickbooks
3
+ module Types
4
+ class AMTTYPE < Type
5
+ native Quickbooks::Support::Amount
6
+ end
7
+ class BOOLTYPE < Type
8
+ native Boolean
9
+ end
10
+ class DATETIMETYPE < Type
11
+ native Quickbooks::Support::DateTime
12
+ end
13
+ class DATETYPE < Type
14
+ require 'date'
15
+ native Quickbooks::Support::Date
16
+ end
17
+ class ENUMTYPE < Type
18
+ native String
19
+ # Need to create the Enum functionality. The dtd's don't specify the allowed values for any of the ENUMTYPEs.
20
+ # For example, the JobStatus property holds one of the following:
21
+ # Awarded, Closed, InProgress, None [DEFAULT], NotAwarded, Pending
22
+ # But there is yet no way to specify allowed values or to validate them.
23
+ class << self
24
+ def enum(in_klass,*args)
25
+ @enum ||= {}
26
+ @enum[in_klass] = args
27
+ end
28
+ end
29
+ end
30
+ class FLOATTYPE < Type
31
+ native Quickbooks::Support::Float
32
+ end
33
+ class GUIDTYPE < Type
34
+ native String
35
+ end
36
+ class IDTYPE < Type
37
+ native String
38
+ end
39
+ class INTTYPE < Type
40
+ native Quickbooks::Support::Integer
41
+ end
42
+ class PERCENTTYPE < Type
43
+ native String
44
+ end
45
+ class PRICETYPE < Type
46
+ native String
47
+ end
48
+ class QUANTYPE < Type
49
+ native Quickbooks::Support::Float
50
+ end
51
+ class STRTYPE < Type
52
+ native String
53
+ end
54
+ class TIMEINTERVALTYPE < Type
55
+ native Quickbooks::Support::TimeInterval
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,10 @@
1
+ module Quickbooks #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 9
5
+ TINY = 9
6
+ BUILD_DATE = '2009-08-05'
7
+
8
+ STRING = [MAJOR, MINOR, TINY].join('.')
9
+ end
10
+ end
@@ -0,0 +1,243 @@
1
+ class Class
2
+ def cascading_attr_reader(*names)
3
+ names.each do |name|
4
+ class_eval "def #{name}; @#{name} || (parent ? parent.#{name} : nil); end"
5
+ end
6
+ end
7
+
8
+ def cascading_attr_accessor(*names)
9
+ names.each do |name|
10
+ attr_writer name
11
+ class_eval "def #{name}; @#{name} || (parent ? parent.#{name} : nil); end"
12
+ end
13
+ end
14
+ end
15
+
16
+ req_base = File.dirname(__FILE__)
17
+ require req_base + '/xsd/xml_parse'
18
+ require req_base + '/xsd/validation'
19
+ require req_base + '/xsd/element'
20
+ require req_base + '/xsd/group'
21
+ require req_base + '/xsd/sequence'
22
+ require req_base + '/xsd/simple_type'
23
+ require req_base + '/xsd/complex_type'
24
+ require req_base + '/xsd/restriction'
25
+ require req_base + '/xsd/choice'
26
+ require req_base + '/xsd/union'
27
+ require req_base + '/xsd/attribute'
28
+
29
+ module Quickbooks
30
+ class XSD
31
+ def inspect
32
+ properties_size = properties.size
33
+ sprintf("#<%s:0x%x %s models, %s elements, %s properties, %s types>", self.class.name, __id__, models.size, elements.size - properties_size, properties_size, types.size)
34
+ end
35
+
36
+ def source_paths
37
+ @source_paths ||= []
38
+ end
39
+ def source_path
40
+ source_paths.last
41
+ end
42
+
43
+ def elements
44
+ @elements ||= {}
45
+ end
46
+ def groups
47
+ @groups ||= {}
48
+ end
49
+ def types
50
+ @types ||= {}
51
+ end
52
+
53
+ def properties
54
+ Hash[*elements.select {|k,e| e.is_property?}.flatten]
55
+ end
56
+ def models
57
+ Hash[*elements.select {|k,e| e.is_model?}.flatten]
58
+ end
59
+
60
+ # Get any name that is saved in elements.
61
+ def [](key)
62
+ elements[key]
63
+ end
64
+ def include?(key)
65
+ elements.include?(key)
66
+ end
67
+
68
+ def self.parse_file(file, path=nil)
69
+ Quickbooks::XSD.new.parse_file(file, path)
70
+ end
71
+
72
+ def parse_file(file, path=nil)
73
+ file = (path || source_path) + '/' + file unless path.nil? && source_path.nil?
74
+
75
+ if File.exists?(file)
76
+ file = File.expand_path(file)
77
+ source_paths << File.dirname(file)
78
+ # puts "Parsing #{file}..."
79
+ xsd = parse(File.read(file))
80
+ source_paths.pop
81
+ xsd
82
+ else
83
+ raise "XSD source file #{file} does not exist!"
84
+ end
85
+ end
86
+
87
+ def parse(source)
88
+ element_stack = []
89
+ waiting_types = Hash.new {|h,k| h[k] = []}
90
+ parser = REXML::Parsers::BaseParser.new(source)
91
+ status = {}
92
+ loop do
93
+ event = parser.pull
94
+ case event[0]
95
+ when :end_document
96
+ break
97
+ when :end_doctype, :start_doctype
98
+ # do nothing
99
+ when :start_element
100
+ # Create a node
101
+ tag_name, attributes = event[1], event[2]
102
+ case tag_name
103
+ when 'xsd:schema'
104
+ # Just the schema element at the top.
105
+
106
+ when 'xsd:include' # Parse this file at this point before continuing.
107
+ parse_file(attributes['schemaLocation'], source_path)
108
+
109
+ when 'xsd:element' # an element. If inside another element any number of levels deep, it's not a declaration, just an inclusion.
110
+ if type_name = attributes.delete('type')
111
+ type = types[type_name]
112
+ attributes.merge!('type' => type)
113
+ end
114
+ element = if element_stack.empty?
115
+ (elements[attributes['name']] ||= Element.new).merge!(attributes)
116
+ elsif attributes.has_key?('ref')
117
+ (elements[attributes['ref']] ||= Element.new).merge(attributes)
118
+ elsif elements.has_key?(attributes['name'])
119
+ elements[attributes['name']].merge(attributes)
120
+ elsif attributes.has_key?('name') && attributes.has_key?('type')
121
+ elements[attributes['name']] ||= Element.new(attributes)
122
+ else
123
+ Element.new(attributes)
124
+ end
125
+ waiting_types[type_name] << element if type_name && type.nil? # When the type is created it will retroactively set the type to this element.
126
+ element_stack.last << element unless element_stack.empty?
127
+ element_stack << element
128
+
129
+ when 'xsd:simpleType' # simpleType means its parent is a property and this defines the possible value
130
+ # If it's being declared on the top level, create a new one
131
+ type = (types[attributes['name']] || SimpleType.new).merge(attributes)
132
+ if element_stack.empty?
133
+ types[type.name] = type
134
+ else
135
+ element_stack.last << type
136
+ end
137
+ element_stack << type
138
+ waiting_types.delete(type.name).each {|e| e.type = type} if type.name && waiting_types.has_key?(type.name)
139
+
140
+ when 'xsd:complexType' # defines a complex requirement, usually a sequence
141
+ # If it's being declared on the top level, create a new one
142
+ type = (types[attributes['name']] || ComplexType.new).merge(attributes)
143
+ if element_stack.empty?
144
+ types[type.name] = type
145
+ else
146
+ element_stack.last << type
147
+ end
148
+ element_stack << type
149
+ waiting_types.delete(type.name).each {|e| e.type = type} if type.name && waiting_types.has_key?(type.name)
150
+
151
+ when 'xsd:restriction' # restriction defines a restriction on the possible value of an element
152
+ element_stack.last.restriction = Restriction.new(attributes)
153
+ element_stack.last.type = types[attributes['base']] # Sets the base type onto the parent SimpleType
154
+ # TODO: currently we don't step into these restrictions, we're referencing them more explicitly (see xsd:enumeration below)
155
+
156
+ when 'xsd:enumeration' # enumerates the values for an ENUM property
157
+ element_stack.last.restriction.enum_values! << attributes.delete('value')
158
+ puts "More attributes for Enumeration: #{attributes.inspect}" unless attributes.empty?
159
+
160
+ when 'xsd:group' # defines a group of elements used together
161
+ group = if element_stack.empty?
162
+ # being declared by name. Save the new attributes into it for sure.
163
+ (groups[attributes['name']] ||= Group.new).merge!(attributes)
164
+ elsif attributes.has_key?('ref')
165
+ # We are referencing a common element, which may or may not already be declared.
166
+ groups[attributes['ref']] ||= Group.new
167
+ else
168
+ # We're not declaring nor are we referencing a declared element.
169
+ Group.new
170
+ end.merge(attributes)
171
+ element_stack.last << group unless element_stack.empty?
172
+ element_stack << group
173
+
174
+ when 'xsd:sequence' # defines a sequence of elements/element-groups
175
+ sequence = Sequence.new(attributes)
176
+ element_stack.last << sequence
177
+ element_stack << sequence
178
+
179
+ when 'xsd:choice' # choice means include any one of the enclosed elements/element-groups
180
+ choice = Choice.new(attributes)
181
+ element_stack.last << choice
182
+ element_stack << choice
183
+ puts "More attributes for Choice: #{attributes.inspect}" unless attributes.empty?
184
+
185
+ when 'xsd:union'
186
+ union = Union.new(attributes)
187
+ element_stack.last << union
188
+ element_stack << union
189
+ puts "More attributes for Union: #{attributes.inspect}" unless attributes.empty?
190
+
191
+ when 'xsd:attribute' # an attribute of the parent element
192
+ if type = attributes.delete('type')
193
+ type = types[type] # assuming that all types are declared before they're referenced.
194
+ attributes.merge!('type' => type)
195
+ end
196
+ attribute = Attribute.new(attributes)
197
+ element_stack.last << attribute
198
+ element_stack << attribute
199
+
200
+ when 'xsd:maxLength' # a restriction of a STRTYPE property
201
+ element_stack.last.restriction.maxLength = attributes.delete('value')
202
+ puts "More attributes for maxLength: #{attributes.inspect}" unless attributes.empty?
203
+
204
+ when 'xsd:pattern' # a restriction of a STRTYPE property
205
+ element_stack.last.restriction.pattern = attributes.delete('value')
206
+ puts "More attributes for pattern: #{attributes.inspect}" unless attributes.empty?
207
+
208
+ when 'xsd:maxInclusive'
209
+ when 'xsd:minInclusive'
210
+ when 'xsd:simpleContent'
211
+ when 'xsd:extension'
212
+ else
213
+ warn "!! Other element: #{tag_name} (#{attributes.inspect})"
214
+ end
215
+ when :end_element
216
+ name = event[1]
217
+ case name
218
+ when 'xsd:element'
219
+ element_stack.pop
220
+ when 'xsd:simpleType'
221
+ element_stack.pop
222
+ when 'xsd:group'
223
+ element_stack.pop
224
+ when 'xsd:union'
225
+ element_stack.pop
226
+ when 'xsd:choice'
227
+ element_stack.pop
228
+ when 'xsd:sequence'
229
+ element_stack.pop
230
+ when 'xsd:complexType'
231
+ element_stack.pop
232
+ when 'xsd:attribute'
233
+ element_stack.pop
234
+ end
235
+ when :text, :cdata
236
+ puts "!! Text Data: #{event[1]}" if event[1].strip.length > 0
237
+ end
238
+ end
239
+
240
+ self
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,57 @@
1
+ module Quickbooks
2
+ class XSD
3
+ class Attribute
4
+ attr_reader :name, :use, :default
5
+ attr_accessor :type
6
+
7
+ def initialize(attributes)
8
+ @name = attributes.delete('name')
9
+ @type = attributes.delete('type')
10
+ @use = attributes.delete('use')
11
+ @default = attributes.delete('default')
12
+ warn "!! Unhandled Attribute attributes: #{attributes.keys.join(', ')}" if !attributes.empty?
13
+ end
14
+
15
+ def items
16
+ @items ||= []
17
+ end
18
+
19
+ def <<(something)
20
+ case something
21
+ when SimpleType
22
+ self.type = something
23
+ else
24
+ items << something
25
+ end
26
+ end
27
+
28
+ def validate(object,required=true)
29
+ return Valean.perfect!(name, required) if object.is_a?(Quickbooks::Model)
30
+ # Validate the object's contents
31
+ puts "#{$DEBUG<<"\t"}Validating #{required ? 'REQUIRED' : 'OPTIONAL'} Attribute #{name}" if $DEBUG
32
+ # A) am I required?
33
+ # B) do I exist?
34
+ # TODO: Also validate by @type
35
+ r = Valean.new(name, required, :exists => !object[name].nil?)
36
+ $DEBUG.chop! if $DEBUG
37
+ puts "#{$DEBUG}\t- #{r}" if $DEBUG
38
+ r
39
+ end
40
+
41
+ def inspect
42
+ "<Attribute: '#{name}' #{use if use} #{type.inspect} #{"default="+default.inspect if default}>".gsub(/ +/,' ').gsub(/ >/,'>')
43
+ end
44
+
45
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is required within its container.
46
+ def required?(key_or_xsd=nil)
47
+ @use == 'required'
48
+ end
49
+ def include?(key_or_xsd)
50
+ false
51
+ end
52
+ def children
53
+ []
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,94 @@
1
+ module Quickbooks
2
+ class XSD
3
+ class Choice
4
+ attr_accessor :sequence
5
+
6
+ def initialize(attributes)
7
+ @minOccurs = (attributes.delete('minOccurs') || 1).to_i
8
+ @maxOccurs = attributes.delete('maxOccurs')
9
+ @items = attributes.delete(:items)
10
+ puts "More attributes for Choice: #{attributes.inspect}" unless attributes.empty?
11
+ end
12
+
13
+ def name
14
+ "either of (#{children.collect {|e| e.name}.join(', ')})"
15
+ end
16
+
17
+ def items
18
+ @items ||= []
19
+ end
20
+
21
+ def <<(something)
22
+ self.items << something
23
+ end
24
+
25
+ def inspect
26
+ sprintf("\n%s", items.map{|i|i.inspect.gsub(/\n/,"\n ")}.join("\n OR"))
27
+ end
28
+
29
+ def clone
30
+ self.class.new('minOccurs' => @minOccurs, 'maxOccurs' => @maxOccurs, :items => items.map {|i| i.clone})
31
+ end
32
+
33
+ # true if present and valid, or optional and missing
34
+ # false if required and either missing or invalid content
35
+ # :invalid if optional and invalid content
36
+ def validate(object,required=true)
37
+ # Validate the object's contents
38
+ puts "#{$DEBUG<<"\t"}Validating CONFORMS TO #Choice (#{required ? 'REQUIRED' : 'OPTIONAL'})" if $DEBUG
39
+ # 1) Is it required?
40
+ r = Valean.new(nil,required)
41
+ # 2) Do any of the choices exist? (if not, choice is missing)
42
+ # TODO: PROBLEM WITH THIS LINE -- DOESN'T ALWAYS FIND EXISTENCE!!!
43
+ existing = items.select {|i| i.exists_in?(object)}
44
+ r.exists! if existing.length > 0
45
+ # 3) Does ONLY ONE of the choices exist? (if not, choice itself is invalid)
46
+ r.invalid!("Must only include 1 of #{children.collect {|e| e.name}.inspect}") if existing.length > 1
47
+ # 4) Is the existing choice valid? (if not, the item is invalid)
48
+ r << existing[0].validate(object) if !existing.empty? && r.perfect?
49
+ $DEBUG.chop! if $DEBUG
50
+ puts "#{$DEBUG}\t- #{r}" if $DEBUG
51
+ r
52
+ end
53
+
54
+ def exists_in?(other)
55
+ items.any? {|i| i.exists_in?(other)}
56
+ end
57
+
58
+ def find(key)
59
+ children.select {|i| i.name == key}[0]
60
+ end
61
+
62
+ def include?(key_or_xsd)
63
+ key_or_xsd.is_a?(String) ?
64
+ children.collect {|e| e.name}.include?(key_or_xsd) :
65
+ (key_or_xsd == self || items.any? {|i| i.include?(key_or_xsd)})
66
+ end
67
+
68
+ def index(key)
69
+ children.collect {|e| e.name}.index(key.to_s)
70
+ end
71
+
72
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is allowed more than once in its parent.
73
+ def repeatable?(key=nil)
74
+ if key
75
+ # puts "Checking repeatable: #{items.inspect}"
76
+ repeatable? || items.any? {|i| i.include?(key) && i.repeatable?(key)}
77
+ else
78
+ @maxOccurs == 'unbounded'
79
+ end
80
+ end
81
+
82
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is required within its container.
83
+ def required?(key_or_xsd=nil)
84
+ (key_or_xsd && @minOccurs > 0) || false
85
+ end
86
+
87
+ def children
88
+ children = []
89
+ items.map {|i| i.is_a?(Quickbooks::XSD::Element) ? children << i : children.concat(i.children)}
90
+ children
91
+ end
92
+ end
93
+ end
94
+ end