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,77 @@
1
+ module Quickbooks
2
+ class XSD
3
+ class Type
4
+ end
5
+ class ComplexType < Type
6
+ attr_reader :name
7
+ attr_accessor :restriction
8
+
9
+ def initialize(attributes={})
10
+ @name = attributes.delete('name')
11
+ @items = attributes.delete(:items)
12
+ warn "!! Unhandled complex type attributes: #{attributes.keys.join(', ')}" if !attributes.empty?
13
+ end
14
+
15
+ def items
16
+ @items ||= []
17
+ end
18
+
19
+ def <<(something)
20
+ items << something
21
+ end
22
+
23
+ def merge(attributes)
24
+ self.class.new({'name' => @name}.merge(attributes))
25
+ end
26
+
27
+ def clone
28
+ self.class.new('name' => @name, :items => items.map {|i| i.clone})
29
+ end
30
+
31
+ def inspect
32
+ sprintf("... >%s", items.map{|i|i.inspect.gsub(/\n/,"\n ")})
33
+ end
34
+
35
+ def validate(object,required=true)
36
+ # Validate the object's contents
37
+ puts "#{$DEBUG<<"\t"}Validating CONFORMS TO #ComplexType #{name} (#{required ? 'REQUIRED' : 'OPTIONAL'})" if $DEBUG
38
+ r = items.inject(Valean.new) {|r,i| r << i.validate(object,required?(i)); r}
39
+ $DEBUG.chop! if $DEBUG
40
+ puts "#{$DEBUG}\t- #{r}" if $DEBUG
41
+ r
42
+ end
43
+
44
+ def find(key)
45
+ children.select {|i| i.name == key}[0]
46
+ end
47
+
48
+ def include?(key_or_xsd)
49
+ key_or_xsd.is_a?(String) ?
50
+ children.collect {|e| e.name}.include?(key_or_xsd) :
51
+ (key_or_xsd == self || items.any? {|i| i.include?(key_or_xsd)})
52
+ end
53
+
54
+ def index(key)
55
+ children.collect {|e| e.name}.index(key.to_s)
56
+ end
57
+
58
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is allowed more than once in its parent.
59
+ def repeatable?(key)
60
+ items.any? {|i| i.include?(key) && i.repeatable?(key)}
61
+ end
62
+
63
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is required within its container.
64
+ def required?(key_or_xsd)
65
+ key_or_xsd.is_a?(String) ?
66
+ items.any? {|i| i.include?(key_or_xsd) && i.required?(key_or_xsd)} :
67
+ (key_or_xsd == self || items.select {|i| i.include?(key_or_xsd)}.any? {|i| i.required?(key_or_xsd)})
68
+ end
69
+
70
+ def children
71
+ children = []
72
+ items.each {|i| i.is_a?(Quickbooks::XSD::Element) ? children << i : children.concat(i.children)}
73
+ children
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,214 @@
1
+ require 'quickbooks/element'
2
+ require 'quickbooks/property'
3
+ module Quickbooks
4
+ class XSD
5
+ # The basic Element.
6
+ class Element
7
+ attr_reader :ref, :minOccurs, :maxOccurs
8
+ cascading_attr_reader :name, :type, :default
9
+
10
+ def initialize(attributes={})
11
+ @parent = attributes.delete(:parent)
12
+ @name = attributes.delete('name')
13
+ self.type = attributes.delete('type') if attributes.has_key?('type')
14
+ @default = attributes.delete('default') # or nil
15
+ @minOccurs = (attributes.delete('minOccurs') || 1).to_i # default is 1, unless otherwise stated
16
+ @maxOccurs = attributes.delete('maxOccurs') # or nil
17
+ @ref = attributes.delete('ref') # or nil
18
+ warn "!! Unhandled attributes: #{attributes.keys.join(', ')}" if !attributes.empty?
19
+ end
20
+
21
+ def type=(type_or_name)
22
+ return unless type_or_name
23
+ if (@type ||= nil).nil?
24
+ @type = type_or_name.is_a?(Quickbooks::XSD::Type) ? type_or_name : SimpleType.new('name' => type_or_name)
25
+ else
26
+ @type.merge!(type) if type_or_name.is_a?(Quickbooks::XSD::Type)
27
+ end
28
+ end
29
+
30
+ attr_reader :parent
31
+ private :parent
32
+
33
+ def complex?
34
+ type.is_a?(ComplexType)
35
+ end
36
+ alias :is_element? :complex?
37
+ def simple?
38
+ type.is_a?(SimpleType)
39
+ end
40
+ alias :is_property? :simple?
41
+ def is_model?
42
+ name.to_s =~ /Ret$/
43
+ end
44
+ def kind
45
+ # TODO: [Multi-mode] Should return Quickbooks::V6_0::Element or Quickbooks::VCA3_0::Element
46
+ complex? ? Quickbooks::Element : Quickbooks::Property
47
+ end
48
+
49
+ def gsub!(*args,&block)
50
+ if block_given?
51
+ @name = name.gsub(*args) {|*a| yield(*a)} if name.is_a?(String)
52
+ children.each {|c| c.gsub!(*args) {|*a| yield(*a)}}
53
+ else
54
+ @name = name.gsub(*args) if name.is_a?(String)
55
+ children.each {|c| c.gsub!(*args)}
56
+ end
57
+ self
58
+ end
59
+ def gsub(*args,&block)
60
+ if block_given?
61
+ clone.gsub!(*args) {|*a| yield(*a)}
62
+ else
63
+ clone.gsub!(*args)
64
+ end
65
+ end
66
+ def clone
67
+ self.class.new(:parent => @parent, 'name' => "#{name}", 'type' => type.clone, 'default' => @default, 'minOccurs' => @minOccurs, 'maxOccurs' => @maxOccurs, 'ref' => @ref)
68
+ end
69
+
70
+ def merge(attributes)
71
+ self.class.new({:parent => self, 'name' => name, 'type' => type, 'default' => @default, 'minOccurs' => @minOccurs, 'maxOccurs' => @maxOccurs, 'ref' => @ref}.merge(attributes))
72
+ end
73
+
74
+ def merge!(attributes)
75
+ @name = attributes.delete('name') || @name
76
+ self.type = attributes.delete('type') if attributes.has_key?('type')
77
+ @default = attributes.delete('default') || @default
78
+ @minOccurs = (attributes.delete('minOccurs') || @minOccurs).to_i
79
+ @maxOccurs = attributes.delete('maxOccurs') || @maxOccurs
80
+ @ref = attributes.delete('ref') || @ref
81
+ return self
82
+ end
83
+
84
+ def <<(something)
85
+ case something
86
+ when SimpleType
87
+ self.type = something
88
+ when ComplexType
89
+ self.type = something
90
+ else
91
+ warn "Something (#{something.inspect}) not handled by #{inspect}"
92
+ end
93
+ end
94
+
95
+ def inspect
96
+ sprintf("\n<%s%s %s", name || ref, (@minOccurs == 0 ? (@maxOccurs == 'unbounded' ? '*' : '?') : (@maxOccurs == 'unbounded' ? '+' : '')), type.inspect) + (type.is_a?(ComplexType) ? '' : '>')
97
+ end
98
+
99
+ def to_class(klass_name)
100
+ puts "Classifying #{klass_name}/#{kind}..." if $DEBUG
101
+ begin
102
+ if name == klass_name+'Ret' || name == klass_name+'Add' || name == klass_name+'Mod'
103
+ # Generate a Model
104
+ # TODO: [Multi-mode] Should generate Quickbooks::V6_0::Models or Quickbooks::VCA3_0::Models container modules on-demand
105
+ const = Quickbooks::Models.const_set(klass_name, ::Class.new(Quickbooks::Model))
106
+
107
+ const.write_xsd(Quickbooks.xsd["#{klass_name}Add"].gsub(/Add$/,'')) if Quickbooks.xsd.include?("#{klass_name}Add")
108
+ const.read_write_xsd(
109
+ Quickbooks.xsd["#{klass_name}Mod"].gsub(/(.*)Mod$/) {|m| Quickbooks.xsd.include?(m.gsub(/Mod$/,'Ret')) ? m.gsub(/Mod$/,'') : m}
110
+ ) if Quickbooks.xsd.include?("#{klass_name}Mod")
111
+
112
+ const.read_xsd(Quickbooks.xsd["#{klass_name}Ret"].gsub(/Ret$/,'')) if Quickbooks.xsd.include?("#{klass_name}Ret")
113
+
114
+ const.query_xsd(Quickbooks.xsd["#{klass_name}QueryRq"]) if Quickbooks.xsd.include?("#{klass_name}QueryRq")
115
+
116
+ else
117
+ # Generate an Element
118
+ # TODO: [Multi-mode] Should generate Quickbooks::V6_0::Elements or Quickbooks::VCA3_0::Elements container modules on-demand
119
+ const = kind.pluralize.const_set(klass_name, ::Class.new(kind))
120
+ const.xsd = self
121
+ end
122
+ rescue => e
123
+ raise e, "Error: #{e.inspect}\n#{e.backtrace.join("\n")}"
124
+ end
125
+ return const
126
+ end
127
+
128
+ include Validation
129
+ # Validate the object's properties, or validate that this property exists within the object.
130
+ def validate(object,required=true)
131
+ if object.class.short_name == name || (object.is_a?(Hash) && object.has_key?(name))
132
+ # Validate the object's contents
133
+ object = object[name] if object.is_a?(Hash)
134
+ puts "#{$DEBUG<<"\t"}Validating\n#{object.inspect}\n#{$DEBUG} CONFORMS TO #{name} (#{required ? 'REQUIRED' : 'OPTIONAL'})" if $DEBUG
135
+ r = type.validate(object,required?(type))
136
+ $DEBUG.chop! if $DEBUG
137
+ else
138
+ puts "#{$DEBUG<<"\t"}Validating #{required ? 'REQUIRED' : 'OPTIONAL'} #{name}" if $DEBUG
139
+ # Validate this (self) property of object
140
+ # puts "Validating #{inspect} IN #{object.inspect}"
141
+ # A) am I required?
142
+ r = Valean.new(name,required)
143
+ # B) do I exist?
144
+ r.exists! if exists_in?(object)
145
+ # C) if exists, do I validate with my own requirements?
146
+ objects = object[name].is_a?(Enumerable) ? object[name] : [object[name]]
147
+ r << validate_these(objects) if r.exists?
148
+ $DEBUG.chop! if $DEBUG
149
+ end
150
+ puts "#{$DEBUG}\t- #{r}" if $DEBUG
151
+ r
152
+ end
153
+
154
+ def exists_in?(object)
155
+ !(object[name].is_a?(Enumerable) ? object[name].empty? : object[name].nil?)
156
+ end
157
+
158
+ def find(key)
159
+ name == key ? self : children.select {|i| i.name == key}[0]
160
+ end
161
+ alias :[] :find
162
+
163
+ # Report whether a named Quickbooks::XSD::Element or any xsd object is a descendent of self.
164
+ def include?(key_or_xsd)
165
+ raise "#{self} not defined properly! This is a BUG! Please report to behindlogic.lighthouseapp.com." if !key_or_xsd.is_a?(String) && type.nil?
166
+ key_or_xsd.is_a?(String) ?
167
+ (name == key_or_xsd ? true : children.collect {|e| e.name}.include?(key_or_xsd)) :
168
+ (key_or_xsd == self || type.include?(key_or_xsd))
169
+ end
170
+
171
+ # Report the position of a named Quickbooks::XSD::Element
172
+ def index(key)
173
+ children.collect {|e| e.name}.index(key.to_s)
174
+ end
175
+
176
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is allowed more than once in its parent.
177
+ def repeatable?(key=nil)
178
+ if key
179
+ found = find(key)
180
+ return nil unless found
181
+ found.repeatable? || type.repeatable?(key)
182
+ else
183
+ @maxOccurs == 'unbounded'
184
+ end
185
+ end
186
+
187
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is required within its container.
188
+ def required?(key_or_xsd)
189
+ if key_or_xsd.is_a?(String)
190
+ if found = find(key_or_xsd)
191
+ found.required?(found) || type.required?(found)
192
+ else
193
+ nil
194
+ end
195
+ else
196
+ (key_or_xsd == self && @minOccurs > 0) || type.required?(key_or_xsd)
197
+ end
198
+ end
199
+
200
+ def attributes
201
+ children.collect {|i| i.name}
202
+ end
203
+
204
+ # Return the closest-descended child elements
205
+ def children
206
+ begin
207
+ @children ||= type.children
208
+ rescue => e
209
+ raise e, "In object #{inspect}"
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,94 @@
1
+ module Quickbooks
2
+ class XSD
3
+ # Group of elements, so that we can refer to them by name...
4
+ class Group
5
+ attr_reader :name, :ref, :minOccurs, :maxOccurs
6
+
7
+ def initialize(attributes={})
8
+ @name = attributes.delete('name')
9
+ @ref = attributes.delete('ref')
10
+ @minOccurs = attributes.delete('minOccurs')
11
+ @maxOccurs = attributes.delete('maxOccurs')
12
+ @items = attributes.delete(:items)
13
+ puts "EG Attributes: #{attributes.inspect}" unless attributes.empty?
14
+ end
15
+
16
+ def items
17
+ @items ||= []
18
+ end
19
+
20
+ def <<(something)
21
+ items << something
22
+ end
23
+
24
+ def merge(attributes)
25
+ self.class.new({'name' => @name, 'ref' => @ref, 'minOccurs' => @minOccurs, 'maxOccurs' => @maxOccurs, :items => items}.merge(attributes))
26
+ end
27
+
28
+ def merge!(attributes)
29
+ @name = attributes.delete('name') || @name
30
+ @ref = attributes.delete('ref') || @ref
31
+ @minOccurs = attributes.delete('minOccurs') || @minOccurs
32
+ @maxOccurs = attributes.delete('maxOccurs') || @maxOccurs
33
+ return self
34
+ end
35
+
36
+ def inspect
37
+ items.map {|i| i.inspect}.join
38
+ end
39
+
40
+ def clone
41
+ self.class.new('name' => @name, 'ref' => @ref, 'minOccurs' => @minOccurs, 'maxOccurs' => @maxOccurs, :items => items.map {|i| i.clone})
42
+ end
43
+
44
+ # include Validations
45
+ def validate(object,required=true)
46
+ # Validate the object's contents
47
+ puts "#{$DEBUG<<"\t"}Validating CONFORMS TO Group[#{name}]" if $DEBUG
48
+ # 1) is it required?
49
+ # 2) do all items exist?
50
+ # 3) are all items valid?
51
+ r = items.inject(Valean.new(nil, required, :exists => true)) {|r,i| r << i.validate(object,required?(i)); r}
52
+ $DEBUG.chop! if $DEBUG
53
+ puts "#{$DEBUG}\t- #{r}" if $DEBUG
54
+ r
55
+ end
56
+
57
+ def exists_in?(object)
58
+ items.any? {|i| i.exists_in?(object)}
59
+ end
60
+
61
+ def find(key)
62
+ children.select {|i| i.name == key}[0]
63
+ end
64
+
65
+ def include?(key_or_xsd)
66
+ key_or_xsd.is_a?(String) ?
67
+ children.collect {|e| e.name}.include?(key_or_xsd) :
68
+ (key_or_xsd == self || items.any? {|i| i.include?(key_or_xsd)})
69
+ end
70
+
71
+ def index(key)
72
+ children.collect {|e| e.name}.index(key.to_s)
73
+ end
74
+
75
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is allowed more than once in its parent.
76
+ def repeatable?(key)
77
+ items.any? {|i| i.include?(key) && i.repeatable?(key)}
78
+ end
79
+
80
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is required within its container.
81
+ def required?(key_or_xsd)
82
+ key_or_xsd.is_a?(String) ?
83
+ items.any? {|i| i.include?(key_or_xsd) && i.required?(key_or_xsd)} :
84
+ (key_or_xsd == self || items.select {|i| i.include?(key_or_xsd)}.any? {|i| i.required?(key_or_xsd)})
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
@@ -0,0 +1,51 @@
1
+ module Quickbooks
2
+ class XSD
3
+ class Restriction
4
+ attr_reader :base
5
+ attr_accessor :maxLength, :pattern
6
+ def enum_values
7
+ @enum_values || []
8
+ end
9
+ def enum_values!
10
+ @enum_values ||= []
11
+ end
12
+
13
+ def initialize(attributes)
14
+ @base = attributes.delete('base')
15
+ @enum_values = attributes.delete(:enum_values)
16
+ @pattern = attributes.delete(:pattern)
17
+ @maxLength = attributes.delete(:maxLength)
18
+ puts "More attributes for Restriction: #{attributes.inspect}" unless attributes.empty?
19
+ end
20
+
21
+ def inspect
22
+ insp = []
23
+ insp << "#{@base.gsub(/(xsd:|TYPE)/,'').capitalize}" if @base
24
+ insp << "max-length:#{@maxLength}" if @maxLength
25
+ insp << "must-match:/#{@pattern}/" if @pattern
26
+ insp << "choice-of:#{@enum_values.inspect}" if @enum_values && !@enum_values.empty?
27
+ insp.join(', ')
28
+ end
29
+
30
+ def pattern
31
+ @pattern ? Regexp.new(@pattern) : nil
32
+ end
33
+
34
+ def validate(object,required=true)
35
+ # Validate the object's contents
36
+ puts "#{$DEBUG<<"\t"}Validating #{object.to_s.inspect} FOLLOWS #{inspect}" if $DEBUG
37
+ r = Valean.new(nil, required, :exists => true)
38
+ r.invalid!("exceeds the max length #{maxLength}") if maxLength && object.to_s.length > maxLength.to_i
39
+ r.invalid!("doesn't match regexp #{pattern}") if r.perfect? && pattern && object.to_s !~ pattern
40
+ r.invalid!("is not one of (#{enum_values.join(', ')})") if r.perfect? && !enum_values.empty? && !enum_values.include?(object.to_s)
41
+ $DEBUG.chop! if $DEBUG
42
+ puts "#{$DEBUG}\t- #{r}" if $DEBUG
43
+ r
44
+ end
45
+
46
+ def clone
47
+ self.class.new('base' => @base.clone, :maxLength => @maxLength, :enum_values => enum_values.map {|i|i})
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,85 @@
1
+ module Quickbooks
2
+ class XSD
3
+ class Sequence
4
+ def initialize(attributes={})
5
+ @items = attributes.delete(:items)
6
+ puts "More attributes for Sequence: #{attributes.inspect}" unless attributes.empty?
7
+ end
8
+
9
+ def items
10
+ @items ||= []
11
+ end
12
+
13
+ def <<(something)
14
+ self.items << something
15
+ end
16
+
17
+ def clone
18
+ self.class.new(:items => items.map {|i| i.clone})
19
+ end
20
+
21
+ def inspect
22
+ items.map {|i|i.inspect}.join
23
+ end
24
+
25
+ include Validation
26
+ def validate(object,required=true)
27
+ # Validate the object's contents
28
+ puts "#{$DEBUG<<"\t"}Validating CONFORMS TO #Sequence (#{required ? 'REQUIRED' : 'OPTIONAL'})" if $DEBUG
29
+ # 1) is it required?
30
+ # 2) do all required children exist?
31
+ # 3) are all existing children valid?
32
+ r = Valean.new(nil, required, :exists => true)
33
+ missings = []
34
+ items.each do |i|
35
+ v = i.validate(object,required?(i))
36
+ r << v
37
+ missings << (i.respond_to?(:name) ? i.name : i) if v.required? && v.missing?
38
+ end
39
+ # (a sequence is also invalid if any are missing)
40
+ r.invalid!("missing required element#{'s' if missings.length > 1} #{missings.join(', ')}") if r.missing?
41
+ $DEBUG.chop! if $DEBUG
42
+ puts "#{$DEBUG}\t- #{r}" if $DEBUG
43
+ r
44
+ end
45
+
46
+ def exists_in?(object)
47
+ items.any? {|i| i.exists_in?(object)}
48
+ end
49
+
50
+ def find(key)
51
+ children.select {|i| i.name == key}[0]
52
+ end
53
+
54
+ # Report whether a named Quickbooks::XSD::Element or any xsd object is a descendent of self.
55
+ def include?(key_or_xsd)
56
+ key_or_xsd.is_a?(String) ?
57
+ children.collect {|e| e.name}.include?(key_or_xsd) :
58
+ (key_or_xsd == self || items.any? {|i| i.include?(key_or_xsd)})
59
+ end
60
+
61
+ # Report the position of a named Quickbooks::XSD::Element
62
+ def index(key)
63
+ children.collect {|e| e.name}.index(key.to_s)
64
+ end
65
+
66
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is allowed more than once in its parent.
67
+ def repeatable?(key)
68
+ items.any? {|i| i.include?(key) && i.repeatable?(key)}
69
+ end
70
+
71
+ # Reports whether the named Quickbooks::XSD::Element or other xsd object is required within its container.
72
+ def required?(key_or_xsd)
73
+ key_or_xsd.is_a?(String) ?
74
+ items.any? {|i| i.include?(key_or_xsd) && i.required?(key_or_xsd)} :
75
+ (key_or_xsd == self || items.select {|i| i.include?(key_or_xsd)}.any? {|i| i.required?(key_or_xsd)})
76
+ end
77
+
78
+ def children
79
+ children = []
80
+ items.map {|i| i.is_a?(Quickbooks::XSD::Element) ? children << i : children.concat(i.children)}
81
+ children
82
+ end
83
+ end
84
+ end
85
+ end