spiderfw 0.5

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 (638) hide show
  1. data/README +4 -0
  2. data/Rakefile +74 -0
  3. data/apps/cas_server/_init.rb +23 -0
  4. data/apps/cas_server/config/options.rb +9 -0
  5. data/apps/cas_server/controllers/mixins/cas_login_mixin.rb +353 -0
  6. data/apps/cas_server/lib/cas.rb +329 -0
  7. data/apps/cas_server/lib/utils.rb +30 -0
  8. data/apps/cas_server/models/login_ticket.rb +11 -0
  9. data/apps/cas_server/models/mixins/consumable.rb +10 -0
  10. data/apps/cas_server/models/proxy_granting_ticket.rb +12 -0
  11. data/apps/cas_server/models/proxy_ticket.rb +12 -0
  12. data/apps/cas_server/models/service_ticket.rb +22 -0
  13. data/apps/cas_server/models/ticket.rb +20 -0
  14. data/apps/cas_server/models/ticket_granting_ticket.rb +15 -0
  15. data/apps/cas_server/views/logout.shtml +3 -0
  16. data/apps/core/admin/_init.rb +23 -0
  17. data/apps/core/admin/admin.rb +17 -0
  18. data/apps/core/admin/controllers/admin_controller.rb +15 -0
  19. data/apps/core/admin/views/index.shtml +1 -0
  20. data/apps/core/admin/views/spider_admin.layout.shtml +23 -0
  21. data/apps/core/admin/widgets/admin_menu/admin_menu.rb +17 -0
  22. data/apps/core/auth/_init.rb +42 -0
  23. data/apps/core/auth/controllers/login_controller.rb +94 -0
  24. data/apps/core/auth/controllers/mixins/auth_helper.rb +114 -0
  25. data/apps/core/auth/controllers/mixins/http_basic_auth.rb +24 -0
  26. data/apps/core/auth/controllers/mixins/http_digest_auth.rb +26 -0
  27. data/apps/core/auth/lib/authenticable.rb +86 -0
  28. data/apps/core/auth/lib/authenticator.rb +11 -0
  29. data/apps/core/auth/lib/digest_authenticator.rb +44 -0
  30. data/apps/core/auth/lib/login_authenticator.rb +27 -0
  31. data/apps/core/auth/models/digest_user.rb +34 -0
  32. data/apps/core/auth/models/group.rb +22 -0
  33. data/apps/core/auth/models/login_user.rb +15 -0
  34. data/apps/core/auth/models/mixins/access_control.rb +71 -0
  35. data/apps/core/auth/models/mixins/authentication_tracking.rb +19 -0
  36. data/apps/core/auth/models/super_user.rb +8 -0
  37. data/apps/core/auth/models/user.rb +15 -0
  38. data/apps/core/auth/po/it/spider_auth.po +33 -0
  39. data/apps/core/auth/po/spider_auth.pot +31 -0
  40. data/apps/core/auth/views/login.shtml +25 -0
  41. data/apps/core/components/_init.rb +21 -0
  42. data/apps/core/components/po/it/spider_components.po +52 -0
  43. data/apps/core/components/po/spider_components.pot +53 -0
  44. data/apps/core/components/public/css/admin.css +73 -0
  45. data/apps/core/components/public/css/crud.css +58 -0
  46. data/apps/core/components/public/css/img/add.gif +0 -0
  47. data/apps/core/components/public/css/img/ajax-loader.gif +0 -0
  48. data/apps/core/components/public/css/img/back.gif +0 -0
  49. data/apps/core/components/public/css/img/bg_header.png +0 -0
  50. data/apps/core/components/public/css/img/body_bg.jpg +0 -0
  51. data/apps/core/components/public/css/img/gray_gradient.gif +0 -0
  52. data/apps/core/components/public/css/img/li_bg.png +0 -0
  53. data/apps/core/components/public/css/img/li_bg_active.png +0 -0
  54. data/apps/core/components/public/css/img/li_bg_hover.png +0 -0
  55. data/apps/core/components/public/css/img/logo.png +0 -0
  56. data/apps/core/components/public/css/img/menu_bg.png +0 -0
  57. data/apps/core/components/public/css/img/menu_bottom.png +0 -0
  58. data/apps/core/components/public/css/img/menu_top.png +0 -0
  59. data/apps/core/components/public/css/img/section-bottom.jpg +0 -0
  60. data/apps/core/components/public/css/list.css +7 -0
  61. data/apps/core/components/public/css/menu.css +47 -0
  62. data/apps/core/components/public/css/spider.css +9 -0
  63. data/apps/core/components/public/css/switcher.css +13 -0
  64. data/apps/core/components/public/css/table.css +99 -0
  65. data/apps/core/components/public/js/inheritance.js +71 -0
  66. data/apps/core/components/public/js/jquery/jquery-1.3.2.js +4376 -0
  67. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  68. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  69. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  70. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  71. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  72. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  73. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  74. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  75. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  76. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  77. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  78. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  79. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  80. data/apps/core/components/public/js/jquery/jquery-ui/css/smoothness/jquery-ui-1.7.2.custom.css +406 -0
  81. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  82. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  83. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  84. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  85. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  86. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  87. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  88. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  89. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  90. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  91. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  92. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  93. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  94. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  95. data/apps/core/components/public/js/jquery/jquery-ui/css/ui-lightness/jquery-ui-1.7.2.custom.css +406 -0
  96. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/AUTHORS.txt +30 -0
  97. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/GPL-LICENSE.txt +278 -0
  98. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/MIT-LICENSE.txt +25 -0
  99. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/bgiframe/ChangeLog.txt +20 -0
  100. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/bgiframe/META.json +32 -0
  101. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/bgiframe/jquery.bgiframe.js +100 -0
  102. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/bgiframe/jquery.bgiframe.min.js +10 -0
  103. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/bgiframe/jquery.bgiframe.pack.js +10 -0
  104. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/bgiframe/test/index.html +197 -0
  105. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/cookie/jquery.cookie.js +97 -0
  106. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/cookie/jquery.cookie.min.js +10 -0
  107. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/cookie/jquery.cookie.pack.js +10 -0
  108. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/cookie/jquery.cookie.zip +0 -0
  109. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/jsdiff/jsdiff.js +159 -0
  110. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/qunit/testrunner.js +780 -0
  111. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/qunit/testsuite.css +120 -0
  112. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/external/simulate/jquery.simulate.js +152 -0
  113. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/jquery-1.3.2.js +4376 -0
  114. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  115. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  116. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  117. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  118. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  119. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  120. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  121. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  122. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-icons_222222_256x240.png +0 -0
  123. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-icons_2e83ff_256x240.png +0 -0
  124. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-icons_454545_256x240.png +0 -0
  125. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-icons_888888_256x240.png +0 -0
  126. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/images/ui-icons_cd0a0a_256x240.png +0 -0
  127. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.accordion.css +9 -0
  128. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.all.css +2 -0
  129. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.base.css +8 -0
  130. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.core.css +37 -0
  131. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.datepicker.css +62 -0
  132. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.dialog.css +13 -0
  133. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.progressbar.css +4 -0
  134. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.resizable.css +13 -0
  135. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.slider.css +17 -0
  136. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.tabs.css +11 -0
  137. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/base/ui.theme.css +245 -0
  138. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  139. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  140. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  141. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  142. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  143. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  144. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  145. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  146. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  147. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  148. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  149. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  150. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  151. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  152. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/jquery-ui-1.7.2.custom.css +406 -0
  153. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.accordion.css +9 -0
  154. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.all.css +2 -0
  155. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.base.css +8 -0
  156. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.core.css +37 -0
  157. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.datepicker.css +62 -0
  158. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.dialog.css +13 -0
  159. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.progressbar.css +4 -0
  160. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.resizable.css +13 -0
  161. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.slider.css +17 -0
  162. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.tabs.css +11 -0
  163. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/themes/ui-lightness/ui.theme.css +247 -0
  164. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.blind.js +49 -0
  165. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.bounce.js +78 -0
  166. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.clip.js +54 -0
  167. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.core.js +545 -0
  168. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.drop.js +50 -0
  169. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.explode.js +79 -0
  170. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.fold.js +56 -0
  171. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.highlight.js +48 -0
  172. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.pulsate.js +56 -0
  173. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.scale.js +180 -0
  174. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.shake.js +57 -0
  175. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.slide.js +50 -0
  176. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/effects.transfer.js +45 -0
  177. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/jquery-ui-i18n.js +771 -0
  178. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-ar.js +20 -0
  179. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-bg.js +20 -0
  180. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-ca.js +19 -0
  181. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-cs.js +19 -0
  182. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-da.js +19 -0
  183. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-de.js +19 -0
  184. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-el.js +19 -0
  185. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-eo.js +19 -0
  186. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-es.js +19 -0
  187. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-fa.js +19 -0
  188. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-fi.js +19 -0
  189. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-fr.js +19 -0
  190. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-he.js +19 -0
  191. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-hr.js +19 -0
  192. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-hu.js +19 -0
  193. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-hy.js +19 -0
  194. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-id.js +19 -0
  195. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-is.js +19 -0
  196. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-it.js +19 -0
  197. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-ja.js +20 -0
  198. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-ko.js +19 -0
  199. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-lt.js +19 -0
  200. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-lv.js +19 -0
  201. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-ms.js +19 -0
  202. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-nl.js +19 -0
  203. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-no.js +19 -0
  204. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-pl.js +19 -0
  205. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-pt-BR.js +19 -0
  206. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-ro.js +22 -0
  207. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-ru.js +19 -0
  208. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-sk.js +19 -0
  209. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-sl.js +20 -0
  210. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-sq.js +19 -0
  211. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-sr-SR.js +19 -0
  212. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-sr.js +19 -0
  213. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-sv.js +19 -0
  214. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-th.js +19 -0
  215. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-tr.js +19 -0
  216. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-uk.js +25 -0
  217. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-zh-CN.js +19 -0
  218. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/i18n/ui.datepicker-zh-TW.js +19 -0
  219. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/jquery-ui-1.7.2.custom.js +9133 -0
  220. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.accordion.js +477 -0
  221. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.core.js +519 -0
  222. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.datepicker.js +1636 -0
  223. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.dialog.js +671 -0
  224. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.draggable.js +766 -0
  225. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.droppable.js +282 -0
  226. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.progressbar.js +116 -0
  227. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.resizable.js +800 -0
  228. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.selectable.js +257 -0
  229. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.slider.js +558 -0
  230. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.sortable.js +1019 -0
  231. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/ui/ui.tabs.js +685 -0
  232. data/apps/core/components/public/js/jquery/jquery-ui/development-bundle/version.txt +1 -0
  233. data/apps/core/components/public/js/jquery/jquery-ui/index.html +367 -0
  234. data/apps/core/components/public/js/jquery/jquery-ui/js/jquery-1.3.2.min.js +19 -0
  235. data/apps/core/components/public/js/jquery/jquery-ui/js/jquery-ui-1.7.2.custom.min.js +298 -0
  236. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/changelog.txt +27 -0
  237. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/jquery.autocomplete.css +48 -0
  238. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/jquery.autocomplete.js +808 -0
  239. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/jquery.autocomplete.min.js +13 -0
  240. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/jquery.autocomplete.pack.js +12 -0
  241. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/lib/jquery.ajaxQueue.js +116 -0
  242. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/lib/jquery.bgiframe.min.js +10 -0
  243. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/lib/jquery.js +3558 -0
  244. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/lib/thickbox-compressed.js +10 -0
  245. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/lib/thickbox.css +163 -0
  246. data/apps/core/components/public/js/jquery/plugins/jquery-autocomplete/todo +166 -0
  247. data/apps/core/components/public/js/jquery/plugins/jquery.form.js +653 -0
  248. data/apps/core/components/public/js/jquery/plugins/jquery.query-2.1.6.js +224 -0
  249. data/apps/core/components/public/js/jquery/plugins/jquery.url.js +214 -0
  250. data/apps/core/components/public/js/jquery/plugins/jtree/jquery.jtree.1.0.js +187 -0
  251. data/apps/core/components/public/js/jquery/plugins/jtree/jquery.jtree.1.0.min.js +1 -0
  252. data/apps/core/components/public/js/jquery/plugins/jtree/jquery.jtree.spider.1.0.js +193 -0
  253. data/apps/core/components/public/js/jquery/plugins/treeview/changelog.txt +35 -0
  254. data/apps/core/components/public/js/jquery/plugins/treeview/images/ajax-loader.gif +0 -0
  255. data/apps/core/components/public/js/jquery/plugins/treeview/images/file.gif +0 -0
  256. data/apps/core/components/public/js/jquery/plugins/treeview/images/folder-closed.gif +0 -0
  257. data/apps/core/components/public/js/jquery/plugins/treeview/images/folder.gif +0 -0
  258. data/apps/core/components/public/js/jquery/plugins/treeview/images/minus.gif +0 -0
  259. data/apps/core/components/public/js/jquery/plugins/treeview/images/plus.gif +0 -0
  260. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-black-line.gif +0 -0
  261. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-black.gif +0 -0
  262. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-default-line.gif +0 -0
  263. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-default.gif +0 -0
  264. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-famfamfam-line.gif +0 -0
  265. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-famfamfam.gif +0 -0
  266. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-gray-line.gif +0 -0
  267. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-gray.gif +0 -0
  268. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-red-line.gif +0 -0
  269. data/apps/core/components/public/js/jquery/plugins/treeview/images/treeview-red.gif +0 -0
  270. data/apps/core/components/public/js/jquery/plugins/treeview/jquery.treeview.async.js +110 -0
  271. data/apps/core/components/public/js/jquery/plugins/treeview/jquery.treeview.css +74 -0
  272. data/apps/core/components/public/js/jquery/plugins/treeview/jquery.treeview.edit.js +37 -0
  273. data/apps/core/components/public/js/jquery/plugins/treeview/jquery.treeview.js +256 -0
  274. data/apps/core/components/public/js/jquery/plugins/treeview/jquery.treeview.min.js +15 -0
  275. data/apps/core/components/public/js/jquery/plugins/treeview/jquery.treeview.pack.js +16 -0
  276. data/apps/core/components/public/js/jquery/plugins/treeview/jquery.treeview.sortable.js +386 -0
  277. data/apps/core/components/public/js/jquery/plugins/treeview/lib/jquery.cookie.js +92 -0
  278. data/apps/core/components/public/js/jquery/plugins/treeview/lib/jquery.js +3534 -0
  279. data/apps/core/components/public/js/jquery/plugins/treeview/todo +8 -0
  280. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/LICENSE +0 -0
  281. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/README +0 -0
  282. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/jquery.timepickr.css +34 -0
  283. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/jquery.timepickr.js +1413 -0
  284. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/jquery.timepickr.min.js +10 -0
  285. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/222222_256x240_icons_icons.png +0 -0
  286. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/2e83ff_256x240_icons_icons.png +0 -0
  287. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/454545_256x240_icons_icons.png +0 -0
  288. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/888888_256x240_icons_icons.png +0 -0
  289. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/aaaaaa_40x100_textures_01_flat_0.png +0 -0
  290. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/cccccc_40x100_textures_03_highlight_soft_75.png +0 -0
  291. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/cd0a0a_256x240_icons_icons.png +0 -0
  292. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/dadada_40x100_textures_02_glass_75.png +0 -0
  293. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/e6e6e6_40x100_textures_02_glass_75.png +0 -0
  294. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/fbf9ee_40x100_textures_02_glass_55.png +0 -0
  295. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/fef1ec_40x100_textures_05_inset_soft_95.png +0 -0
  296. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/ffffff_40x100_textures_02_glass_65.png +0 -0
  297. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/images/ffffff_40x100_textures_02_glass_75.png +0 -0
  298. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.accordion.css +9 -0
  299. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.all.css +4 -0
  300. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.allplugins.css +7 -0
  301. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.core.css +37 -0
  302. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.datepicker.css +60 -0
  303. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.dialog.css +13 -0
  304. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.progressbar.css +4 -0
  305. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.resizable.css +13 -0
  306. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.slider.css +13 -0
  307. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.tabs.css +9 -0
  308. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.theme.css +238 -0
  309. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/themes/default/ui.timepickr.css +44 -0
  310. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/ui.timepickr.js +2307 -0
  311. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/dist/ui.timepickr.min.js +10 -0
  312. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/body-bg.png +0 -0
  313. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/btn-hover.png +0 -0
  314. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/btn.png +0 -0
  315. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/buttons.psd +0 -0
  316. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/index.html +326 -0
  317. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/jquery.anchorHandler.js +44 -0
  318. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/jquery.strings.js +290 -0
  319. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/jquery.ui.all.js +518 -0
  320. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/jquery.utils.js +255 -0
  321. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/jquery.utils.ui.min.js +26 -0
  322. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/logo-ff.png +0 -0
  323. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/logo-ie.png +0 -0
  324. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/logo.png +0 -0
  325. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/logo.psd +0 -0
  326. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/package.png +0 -0
  327. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/reset.css +48 -0
  328. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/script_code.png +0 -0
  329. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/styles.css +308 -0
  330. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/themeroller_ready_black_200px.gif +0 -0
  331. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/page/weather_sun.png +0 -0
  332. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/src/css/ui.dropslide.css +26 -0
  333. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/src/css/ui.timepickr.css +18 -0
  334. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/src/ui.dropslide.js +132 -0
  335. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/src/ui.timepickr.js +217 -0
  336. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/test/data/testrunner.js +1 -0
  337. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/test/index.html +34 -0
  338. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/test/otherlibs/jquery/1.2.1/jquery.js +11 -0
  339. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/test/otherlibs/jquery/1.2.3/jquery.js +11 -0
  340. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/test/qunit/testrunner.js +780 -0
  341. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/test/qunit/testsuite.css +120 -0
  342. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/test/styles.css +201 -0
  343. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/test/test.js +41 -0
  344. data/apps/core/components/public/js/jquery/plugins/ui-timepickr/test/unit/ui.timepickr.js +154 -0
  345. data/apps/core/components/public/js/list.js +234 -0
  346. data/apps/core/components/public/js/spider.js +484 -0
  347. data/apps/core/components/public/widgets/search_table.js +10 -0
  348. data/apps/core/components/public/widgets/table.js +9 -0
  349. data/apps/core/components/widgets/admin/admin.rb +75 -0
  350. data/apps/core/components/widgets/admin/admin.shtml +16 -0
  351. data/apps/core/components/widgets/confirm/confirm.rb +37 -0
  352. data/apps/core/components/widgets/confirm/confirm.shtml +9 -0
  353. data/apps/core/components/widgets/crud/crud.rb +119 -0
  354. data/apps/core/components/widgets/crud/crud.shtml +59 -0
  355. data/apps/core/components/widgets/crud/form_table/form_table.rb +13 -0
  356. data/apps/core/components/widgets/crud/form_table/form_table.shtml +3 -0
  357. data/apps/core/components/widgets/list/list.rb +294 -0
  358. data/apps/core/components/widgets/list/list.shtml +38 -0
  359. data/apps/core/components/widgets/list/plugins/exportable/exportable_list.rb +19 -0
  360. data/apps/core/components/widgets/list/plugins/exportable/exportable_list.shtml +5 -0
  361. data/apps/core/components/widgets/menu/menu.rb +20 -0
  362. data/apps/core/components/widgets/menu/menu.shtml +13 -0
  363. data/apps/core/components/widgets/search_table/search_table.rb +22 -0
  364. data/apps/core/components/widgets/search_table/search_table.shtml +11 -0
  365. data/apps/core/components/widgets/switcher/switcher.rb +68 -0
  366. data/apps/core/components/widgets/switcher/switcher.shtml +17 -0
  367. data/apps/core/components/widgets/table/table.rb +153 -0
  368. data/apps/core/components/widgets/table/table.shtml +41 -0
  369. data/apps/core/components/widgets/tabs/tabs.rb +38 -0
  370. data/apps/core/components/widgets/tabs/tabs.shtml +2 -0
  371. data/apps/core/forms/_init.rb +22 -0
  372. data/apps/core/forms/po/it/spider_forms.po +36 -0
  373. data/apps/core/forms/po/spider_forms.pot +37 -0
  374. data/apps/core/forms/public/date_time.js +23 -0
  375. data/apps/core/forms/public/form.css +81 -0
  376. data/apps/core/forms/public/form.js +19 -0
  377. data/apps/core/forms/public/input.js +30 -0
  378. data/apps/core/forms/public/search_select.js +123 -0
  379. data/apps/core/forms/public/select.js +11 -0
  380. data/apps/core/forms/tags/element_label.erb +1 -0
  381. data/apps/core/forms/tags/element_row.erb +4 -0
  382. data/apps/core/forms/tags/row.erb +4 -0
  383. data/apps/core/forms/widgets/form/form.rb +430 -0
  384. data/apps/core/forms/widgets/form/form.shtml +47 -0
  385. data/apps/core/forms/widgets/inputs/checkbox/checkbox.rb +13 -0
  386. data/apps/core/forms/widgets/inputs/checkbox/checkbox.shtml +3 -0
  387. data/apps/core/forms/widgets/inputs/date_time/date_time.rb +48 -0
  388. data/apps/core/forms/widgets/inputs/date_time/date_time.shtml +4 -0
  389. data/apps/core/forms/widgets/inputs/hidden/hidden.rb +8 -0
  390. data/apps/core/forms/widgets/inputs/hidden/hidden.shtml +3 -0
  391. data/apps/core/forms/widgets/inputs/input/input.rb +105 -0
  392. data/apps/core/forms/widgets/inputs/input/input.shtml +3 -0
  393. data/apps/core/forms/widgets/inputs/input/readonly.shtml +6 -0
  394. data/apps/core/forms/widgets/inputs/password/password.rb +24 -0
  395. data/apps/core/forms/widgets/inputs/password/password.shtml +5 -0
  396. data/apps/core/forms/widgets/inputs/search_select/search_select.rb +168 -0
  397. data/apps/core/forms/widgets/inputs/search_select/search_select.shtml +42 -0
  398. data/apps/core/forms/widgets/inputs/select/select.rb +126 -0
  399. data/apps/core/forms/widgets/inputs/select/select.shtml +8 -0
  400. data/apps/core/forms/widgets/inputs/subform/subform.rb +10 -0
  401. data/apps/core/forms/widgets/inputs/subform/subform.shtml +5 -0
  402. data/apps/core/forms/widgets/inputs/text/text.rb +9 -0
  403. data/apps/core/forms/widgets/inputs/text/text.shtml +3 -0
  404. data/apps/core/forms/widgets/inputs/text_area/text_area.rb +10 -0
  405. data/apps/core/forms/widgets/inputs/text_area/text_area.shtml +1 -0
  406. data/apps/drb_server/_init.rb +8 -0
  407. data/apps/drb_server/lib/model_server.rb +41 -0
  408. data/apps/drb_server/script/start_server.rb +19 -0
  409. data/apps/hippo/_init.rb +10 -0
  410. data/apps/hippo/models/mixins/hippo_struct.rb +210 -0
  411. data/apps/hippo/models/security_group.rb +21 -0
  412. data/apps/hippo/models/security_user.rb +29 -0
  413. data/apps/messenger/_init.rb +24 -0
  414. data/apps/messenger/config/options.rb +15 -0
  415. data/apps/messenger/config/worker.rb +3 -0
  416. data/apps/messenger/controllers/messenger_controller.rb +80 -0
  417. data/apps/messenger/controllers/mixins/messenger_controller_mixin.rb +54 -0
  418. data/apps/messenger/lib/backends/email/smtp.rb +0 -0
  419. data/apps/messenger/messenger.rb +94 -0
  420. data/apps/messenger/models/email.rb +22 -0
  421. data/apps/messenger/models/message.rb +44 -0
  422. data/apps/messenger/po/it/spider_messenger.po +77 -0
  423. data/apps/messenger/po/spider_messenger.pot +77 -0
  424. data/apps/messenger/views/index.shtml +13 -0
  425. data/apps/messenger/views/list.shtml +5 -0
  426. data/apps/messenger/views/messenger.layout.shtml +4 -0
  427. data/apps/messenger/views/queue.shtml +8 -0
  428. data/apps/messenger/views/tags/sent_messages.shtml +1 -0
  429. data/apps/soap/_init.rb +16 -0
  430. data/apps/soap/controllers/soap_controller.rb +334 -0
  431. data/apps/soap/doc/examples/example.rb +28 -0
  432. data/apps/soap/lib/soap.rb +217 -0
  433. data/apps/sso/_init.rb +16 -0
  434. data/apps/sso/config/options.rb +13 -0
  435. data/apps/sso/controllers/mixins/saml2_mixin.rb +149 -0
  436. data/apps/sso/lib/saml2/backend.rb +16 -0
  437. data/apps/sso/lib/saml2/lasso_backend.rb +88 -0
  438. data/apps/sso/lib/saml2.rb +112 -0
  439. data/apps/sso/views/saml2_post.shtml +19 -0
  440. data/apps/webdav/_init.rb +15 -0
  441. data/apps/webdav/controllers/webdav_controller.rb +862 -0
  442. data/apps/webdav/lib/locking.rb +193 -0
  443. data/apps/webdav/lib/vfs/abstract.rb +78 -0
  444. data/apps/webdav/lib/vfs/local.rb +126 -0
  445. data/apps/webdav/lib/vfs/mapped.rb +235 -0
  446. data/apps/webdav/lib/vfs/properties.rb +41 -0
  447. data/apps/worker/_init.rb +13 -0
  448. data/apps/worker/cmd.rb +65 -0
  449. data/apps/worker/config/options.rb +9 -0
  450. data/apps/worker/lib/runner.rb +43 -0
  451. data/apps/worker/lib/task.rb +9 -0
  452. data/apps/worker/models/job.rb +20 -0
  453. data/apps/worker/worker.rb +168 -0
  454. data/bin/spider +9 -0
  455. data/blueprints/app/_init.rb +10 -0
  456. data/blueprints/app/controllers/__APP___controller.rb +14 -0
  457. data/blueprints/app/views/__APP__.layout.shtml +8 -0
  458. data/blueprints/app/views/index.shtml +3 -0
  459. data/blueprints/install/config/config.yml +14 -0
  460. data/blueprints/install/init.rb +3 -0
  461. data/data/locale/it/LC_MESSAGES/spider.mo +0 -0
  462. data/data/locale/it/LC_MESSAGES/spider_auth.mo +0 -0
  463. data/data/locale/it/LC_MESSAGES/spider_components.mo +0 -0
  464. data/data/locale/it/LC_MESSAGES/spider_forms.mo +0 -0
  465. data/data/locale/it/LC_MESSAGES/spider_messenger.mo +0 -0
  466. data/lib/spiderfw/app.rb +186 -0
  467. data/lib/spiderfw/autoload.rb +12 -0
  468. data/lib/spiderfw/cache/template_cache.rb +136 -0
  469. data/lib/spiderfw/cmd/cmd.rb +72 -0
  470. data/lib/spiderfw/cmd/commands/cert.rb +427 -0
  471. data/lib/spiderfw/cmd/commands/console.rb +27 -0
  472. data/lib/spiderfw/cmd/commands/init.rb +52 -0
  473. data/lib/spiderfw/cmd/commands/model.rb +131 -0
  474. data/lib/spiderfw/cmd/commands/setup.rb +54 -0
  475. data/lib/spiderfw/cmd/commands/test.rb +61 -0
  476. data/lib/spiderfw/cmd/commands/webserver.rb +93 -0
  477. data/lib/spiderfw/config/configurable.rb +38 -0
  478. data/lib/spiderfw/config/configuration.rb +281 -0
  479. data/lib/spiderfw/config/options/spider.rb +122 -0
  480. data/lib/spiderfw/controller/app_controller.rb +14 -0
  481. data/lib/spiderfw/controller/controller.rb +321 -0
  482. data/lib/spiderfw/controller/controller_exceptions.rb +27 -0
  483. data/lib/spiderfw/controller/controller_io.rb +26 -0
  484. data/lib/spiderfw/controller/controller_mixin.rb +12 -0
  485. data/lib/spiderfw/controller/cookie.rb +20 -0
  486. data/lib/spiderfw/controller/cookies.rb +17 -0
  487. data/lib/spiderfw/controller/dispatcher.rb +269 -0
  488. data/lib/spiderfw/controller/first_responder.rb +59 -0
  489. data/lib/spiderfw/controller/formats/html.rb +90 -0
  490. data/lib/spiderfw/controller/helpers/widget_helper.rb +73 -0
  491. data/lib/spiderfw/controller/home_controller.rb +26 -0
  492. data/lib/spiderfw/controller/http_controller.rb +112 -0
  493. data/lib/spiderfw/controller/mixins/http_mixin.rb +228 -0
  494. data/lib/spiderfw/controller/mixins/static_content.rb +90 -0
  495. data/lib/spiderfw/controller/mixins/visual.rb +489 -0
  496. data/lib/spiderfw/controller/page_controller.rb +39 -0
  497. data/lib/spiderfw/controller/request.rb +48 -0
  498. data/lib/spiderfw/controller/response.rb +50 -0
  499. data/lib/spiderfw/controller/router.rb +9 -0
  500. data/lib/spiderfw/controller/scene.rb +27 -0
  501. data/lib/spiderfw/controller/session/file_session.rb +83 -0
  502. data/lib/spiderfw/controller/session/flash_hash.rb +56 -0
  503. data/lib/spiderfw/controller/session/memory_session.rb +62 -0
  504. data/lib/spiderfw/controller/session/transient_hash.rb +18 -0
  505. data/lib/spiderfw/controller/session.rb +106 -0
  506. data/lib/spiderfw/controller/spider_controller.rb +20 -0
  507. data/lib/spiderfw/create.rb +64 -0
  508. data/lib/spiderfw/env.rb +17 -0
  509. data/lib/spiderfw/exceptions.rb +2 -0
  510. data/lib/spiderfw/home.rb +26 -0
  511. data/lib/spiderfw/http/adapters/cgi.rb +62 -0
  512. data/lib/spiderfw/http/adapters/cgi_io.rb +27 -0
  513. data/lib/spiderfw/http/adapters/fcgi.rb +62 -0
  514. data/lib/spiderfw/http/adapters/mongrel.rb +207 -0
  515. data/lib/spiderfw/http/adapters/rack.rb +152 -0
  516. data/lib/spiderfw/http/adapters/thin.rb +38 -0
  517. data/lib/spiderfw/http/adapters/webrick.rb +176 -0
  518. data/lib/spiderfw/http/http.rb +297 -0
  519. data/lib/spiderfw/http/server.rb +40 -0
  520. data/lib/spiderfw/i18n/cldr.rb +114 -0
  521. data/lib/spiderfw/i18n/gettext.rb +8 -0
  522. data/lib/spiderfw/i18n/i18n.rb +120 -0
  523. data/lib/spiderfw/i18n/provider.rb +12 -0
  524. data/lib/spiderfw/i18n/rails.rb +89 -0
  525. data/lib/spiderfw/i18n/shtml_parser.rb +41 -0
  526. data/lib/spiderfw/model/active_record.rb +335 -0
  527. data/lib/spiderfw/model/base_model.rb +2068 -0
  528. data/lib/spiderfw/model/condition.rb +416 -0
  529. data/lib/spiderfw/model/data_type.rb +75 -0
  530. data/lib/spiderfw/model/datatypes/binary.rb +10 -0
  531. data/lib/spiderfw/model/datatypes/bool.rb +10 -0
  532. data/lib/spiderfw/model/datatypes/decimal.rb +22 -0
  533. data/lib/spiderfw/model/datatypes/email.rb +13 -0
  534. data/lib/spiderfw/model/datatypes/password.rb +63 -0
  535. data/lib/spiderfw/model/datatypes/serialized_object.rb +32 -0
  536. data/lib/spiderfw/model/datatypes/text.rb +10 -0
  537. data/lib/spiderfw/model/datatypes/uuid.rb +29 -0
  538. data/lib/spiderfw/model/datatypes.rb +19 -0
  539. data/lib/spiderfw/model/element.rb +250 -0
  540. data/lib/spiderfw/model/extended_models/managed.rb +43 -0
  541. data/lib/spiderfw/model/identity_mapper.rb +89 -0
  542. data/lib/spiderfw/model/inline_model.rb +37 -0
  543. data/lib/spiderfw/model/mappers/db_mapper.rb +1126 -0
  544. data/lib/spiderfw/model/mappers/hash_mapper.rb +114 -0
  545. data/lib/spiderfw/model/mappers/mapper.rb +926 -0
  546. data/lib/spiderfw/model/mappers/mappers.rb +7 -0
  547. data/lib/spiderfw/model/mappers/proxy_mapper.rb +25 -0
  548. data/lib/spiderfw/model/mappers/vfs/flat_file.rb +31 -0
  549. data/lib/spiderfw/model/mixins/converted.rb +110 -0
  550. data/lib/spiderfw/model/mixins/list.rb +135 -0
  551. data/lib/spiderfw/model/mixins/mixins.rb +7 -0
  552. data/lib/spiderfw/model/mixins/state_machine.rb +81 -0
  553. data/lib/spiderfw/model/mixins/synchronized.rb +88 -0
  554. data/lib/spiderfw/model/mixins/tree.rb +296 -0
  555. data/lib/spiderfw/model/mixins/versioned.rb +147 -0
  556. data/lib/spiderfw/model/model.rb +226 -0
  557. data/lib/spiderfw/model/model_hash.rb +50 -0
  558. data/lib/spiderfw/model/proxy_model.rb +37 -0
  559. data/lib/spiderfw/model/query.rb +147 -0
  560. data/lib/spiderfw/model/query_funcs.rb +99 -0
  561. data/lib/spiderfw/model/query_set.rb +700 -0
  562. data/lib/spiderfw/model/request.rb +80 -0
  563. data/lib/spiderfw/model/storage/base_storage.rb +110 -0
  564. data/lib/spiderfw/model/storage/db/adapters/mssql.rb +129 -0
  565. data/lib/spiderfw/model/storage/db/adapters/mysql.rb +436 -0
  566. data/lib/spiderfw/model/storage/db/adapters/oci8.rb +533 -0
  567. data/lib/spiderfw/model/storage/db/adapters/sqlite.rb +163 -0
  568. data/lib/spiderfw/model/storage/db/connectors/odbc.rb +213 -0
  569. data/lib/spiderfw/model/storage/db/db.rb +13 -0
  570. data/lib/spiderfw/model/storage/db/db_connection_pool.rb +126 -0
  571. data/lib/spiderfw/model/storage/db/db_connector.rb +9 -0
  572. data/lib/spiderfw/model/storage/db/db_schema.rb +233 -0
  573. data/lib/spiderfw/model/storage/db/db_storage.rb +872 -0
  574. data/lib/spiderfw/model/storage/db/dialects/no_total_rows.rb +18 -0
  575. data/lib/spiderfw/model/storage/db/reflector.rb +36 -0
  576. data/lib/spiderfw/model/storage/null_storage.rb +18 -0
  577. data/lib/spiderfw/model/storage/schema.rb +19 -0
  578. data/lib/spiderfw/model/storage.rb +72 -0
  579. data/lib/spiderfw/model/sync.rb +94 -0
  580. data/lib/spiderfw/model/type.rb +13 -0
  581. data/lib/spiderfw/model/unit_of_work.rb +75 -0
  582. data/lib/spiderfw/requires.rb +21 -0
  583. data/lib/spiderfw/resource.rb +18 -0
  584. data/lib/spiderfw/setup/setup_task.rb +44 -0
  585. data/lib/spiderfw/tag/tag.rb +28 -0
  586. data/lib/spiderfw/templates/blocks/attr_if.rb +32 -0
  587. data/lib/spiderfw/templates/blocks/comment.rb +38 -0
  588. data/lib/spiderfw/templates/blocks/debugger.rb +16 -0
  589. data/lib/spiderfw/templates/blocks/each.rb +51 -0
  590. data/lib/spiderfw/templates/blocks/html.rb +70 -0
  591. data/lib/spiderfw/templates/blocks/if.rb +35 -0
  592. data/lib/spiderfw/templates/blocks/pass.rb +16 -0
  593. data/lib/spiderfw/templates/blocks/render.rb +23 -0
  594. data/lib/spiderfw/templates/blocks/run.rb +30 -0
  595. data/lib/spiderfw/templates/blocks/tag.rb +21 -0
  596. data/lib/spiderfw/templates/blocks/tag_if.rb +29 -0
  597. data/lib/spiderfw/templates/blocks/text.rb +43 -0
  598. data/lib/spiderfw/templates/blocks/widget.rb +58 -0
  599. data/lib/spiderfw/templates/blocks/yield.rb +18 -0
  600. data/lib/spiderfw/templates/layout.rb +44 -0
  601. data/lib/spiderfw/templates/resources/less.rb +14 -0
  602. data/lib/spiderfw/templates/template.rb +625 -0
  603. data/lib/spiderfw/templates/template_blocks.rb +185 -0
  604. data/lib/spiderfw/utils/annotations.rb +201 -0
  605. data/lib/spiderfw/utils/fork.rb +75 -0
  606. data/lib/spiderfw/utils/hash_comparison.rb +8 -0
  607. data/lib/spiderfw/utils/inflector.rb +42 -0
  608. data/lib/spiderfw/utils/logger.rb +92 -0
  609. data/lib/spiderfw/utils/monkey/class.rb +59 -0
  610. data/lib/spiderfw/utils/monkey/date_time.rb +34 -0
  611. data/lib/spiderfw/utils/monkey/debugger.rb +25 -0
  612. data/lib/spiderfw/utils/monkey/exception.rb +23 -0
  613. data/lib/spiderfw/utils/monkey/kernel.rb +12 -0
  614. data/lib/spiderfw/utils/monkey/module.rb +12 -0
  615. data/lib/spiderfw/utils/monkey/symbol.rb +7 -0
  616. data/lib/spiderfw/utils/monkey/time.rb +17 -0
  617. data/lib/spiderfw/utils/multi_level_hash.rb +33 -0
  618. data/lib/spiderfw/utils/periodic_runner.rb +50 -0
  619. data/lib/spiderfw/utils/rails.rb +78 -0
  620. data/lib/spiderfw/utils/rails_app.rb +53 -0
  621. data/lib/spiderfw/utils/sanitizer.rb +178 -0
  622. data/lib/spiderfw/utils/setup_task.rb +35 -0
  623. data/lib/spiderfw/utils/shared_store/file_shared_store.rb +73 -0
  624. data/lib/spiderfw/utils/shared_store/memory_shared_store.rb +46 -0
  625. data/lib/spiderfw/utils/shared_store.rb +47 -0
  626. data/lib/spiderfw/utils/test_case.rb +24 -0
  627. data/lib/spiderfw/utils/thread_out.rb +24 -0
  628. data/lib/spiderfw/version.rb +3 -0
  629. data/lib/spiderfw/widget/rest_model.rb +20 -0
  630. data/lib/spiderfw/widget/widget.rb +671 -0
  631. data/lib/spiderfw/widget/widget_attributes.rb +54 -0
  632. data/lib/spiderfw/widget/widget_plugin.rb +37 -0
  633. data/lib/spiderfw.rb +509 -0
  634. data/spider.gemspec +43 -0
  635. data/views/errors/404.shtml +6 -0
  636. data/views/errors/error.layout.shtml +70 -0
  637. data/views/errors/error_generic.shtml +6 -0
  638. metadata +800 -0
@@ -0,0 +1,1126 @@
1
+ require 'spiderfw/model/mappers/mapper'
2
+ require 'fileutils'
3
+
4
+
5
+ module Spider; module Model; module Mappers
6
+
7
+ class DbMapper < Spider::Model::Mapper
8
+ include Spider::Model::Storage::Db
9
+
10
+ def initialize(model, storage)
11
+ super
12
+ @type = :db
13
+ end
14
+
15
+ def self.write? #:nodoc:
16
+ true
17
+ end
18
+
19
+ # Checks if the schema has some key to reach element.
20
+ def have_references?(element) #:nodoc:
21
+ element = @model.elements[element] unless element.is_a?(Element)
22
+ schema.has_foreign_fields?(element.name) || schema.field(element.name)
23
+ end
24
+
25
+ def someone_have_references?(element)
26
+ element = @model.elements[element] unless element.is_a?(Element)
27
+ if (element.integrated?)
28
+ return element.model.someone_have_references?(element.attributes[:integrated_from_element])
29
+ end
30
+ return have_references?(element)
31
+ end
32
+
33
+ ##############################################################
34
+ # Save (insert and update) #
35
+ ##############################################################
36
+
37
+ def before_save(obj, mode) #:nodoc:
38
+ super
39
+ end
40
+
41
+ def save_all(root) #:nodoc:
42
+ @storage.start_transaction if @storage.supports_transactions?
43
+ super
44
+ @storage.commit
45
+ end
46
+
47
+ def do_insert(obj) #:nodoc:
48
+ if (obj.model.managed? || !obj.primary_keys_set?)
49
+ assign_primary_keys(obj)
50
+ end
51
+ sql, values = prepare_insert(obj)
52
+ if (sql)
53
+ @storage.execute(sql, *values)
54
+ end
55
+ end
56
+
57
+ def do_update(obj) #:nodoc:
58
+ sql, values = prepare_update(obj)
59
+ if (sql)
60
+ storage.execute(sql, *values)
61
+ end
62
+ end
63
+
64
+ def do_delete(condition, force=false) #:nodoc:
65
+ #delete = prepare_delete(obj)
66
+ del = {}
67
+ del[:condition], del[:joins] = prepare_condition(condition)
68
+ del[:table] = schema.table
69
+ sql, values = storage.sql_delete(del, force)
70
+ storage.execute(sql, *values)
71
+ end
72
+
73
+ # def delete_all!
74
+ # storage.execute("DELETE FROM #{schema.table}")
75
+ # end
76
+
77
+ # Execute SQL directly, returning raw db results.
78
+ def sql_execute(sql, *values)
79
+ storage.execute(sql, *values)
80
+ end
81
+
82
+ # Save preprocessing
83
+ def prepare_save(obj, save_mode, request=nil) #:nodoc:
84
+ values = {}
85
+ obj.no_autoload do
86
+ @model.each_element do |element|
87
+ next if !mapped?(element) || element.integrated?
88
+ next if save_mode == :update && !obj.element_modified?(element)
89
+ if (save_mode == :insert && element.attributes[:autoincrement] && !schema.attributes(element.name)[:autoincrement])
90
+ obj.set(element.name, @storage.sequence_next(schema.sequence(element.name)))
91
+ end
92
+ if (!element.multiple?)
93
+ next if (save_mode == :update && element.primary_key?)
94
+ next if (element.model? && !schema.has_foreign_fields?(element.name))
95
+ next if (element.model? && (!(element_val = obj.get(element)) || !obj.get(element).primary_keys_set?))
96
+ next if (element.integrated?)
97
+ if (element.model?)
98
+ element.model.primary_keys.each do |key|
99
+ # FIXME! only works with one primary key
100
+ if (key.model?)
101
+ key_type = key.model.primary_keys[0].type
102
+ key_value = element_val.get(key.name).get(key.model.primary_keys[0])
103
+ else
104
+ key_type = key.model? ? key.model.primary_keys[0].type : key.type
105
+ key_value = element_val.get(key.name)
106
+ end
107
+ store_key = schema.foreign_key_field(element.name, key.name)
108
+ values[store_key] = map_save_value(key_type, key_value, save_mode)
109
+ end
110
+ else
111
+ store_key = schema.field(element.name)
112
+ values[store_key] = map_save_value(element.type, obj.send(element.name), save_mode)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ return {
118
+ :values => values
119
+ }
120
+ end
121
+
122
+ # Insert preprocessing
123
+ def prepare_insert(obj) #:nodoc:
124
+ save = prepare_save(obj, :insert)
125
+ return nil unless save[:values].length > 0
126
+ save[:table] = @schema.table
127
+ return @storage.sql_insert(save)
128
+ end
129
+
130
+ # Update preprocessing
131
+ def prepare_update(obj) #:nodoc:
132
+ save = prepare_save(obj, :update)
133
+ return nil unless save[:values].length > 0
134
+ condition = Condition.and
135
+ @model.primary_keys.each do |key|
136
+ condition[key.name] = map_condition_value(key.type, obj.get(key))
137
+ end
138
+ prepare_query_condition(condition)
139
+ save[:condition], save[:joins] = prepare_condition(condition)
140
+ save[:joins] = prepare_joins(save[:joins])
141
+ save[:table] = @schema.table
142
+ return @storage.sql_update(save)
143
+ end
144
+
145
+ # Updates according to a condition, storing the values, which must passed as a Hash.
146
+ def bulk_update(values, condition)
147
+ db_values = {}
148
+ joins = []
149
+ integrated = {}
150
+ condition = prepare_query_condition(condition)
151
+ values.each do |key, val|
152
+ element = @model.elements[key]
153
+ if (element.integrated?)
154
+ integrated[element.integrated_from] ||= {}
155
+ integrated[element.integrated_from][key] = val
156
+ next
157
+ end
158
+ next if !mapped?(element)
159
+ next if element.model? && val != nil
160
+ store_key = schema.field(element.name)
161
+ next unless store_key
162
+ if (val.is_a?(Spider::QueryFuncs::Expression))
163
+ joins += prepare_expression(val)
164
+ db_values[store_key] = val
165
+ else
166
+ db_values[store_key] = map_save_value(element.type, val, :update)
167
+ end
168
+ end
169
+ integrated.each do |i_el, i_values|
170
+ next unless condition[i_el.name]
171
+ i_el.mapper.bulk_update(i_values, condition[i_el.name]) # FIXME?
172
+ end
173
+ return if db_values.empty?
174
+ save = {:table => schema.table, :values => db_values}
175
+ condition, c_joins = prepare_condition(condition)
176
+ joins += c_joins
177
+ save[:condition] = condition
178
+ save[:joins] = prepare_joins(joins)
179
+ sql, bind_vars = @storage.sql_update(save)
180
+ return @storage.execute(sql, *bind_vars)
181
+ end
182
+
183
+ # Lock db
184
+ #--
185
+ # FIXME
186
+ def lock(obj=nil, mode=:exclusive) #:nodoc:
187
+ return storage.lock(@schema.table) unless obj
188
+ end
189
+
190
+ # Next value for the named sequence
191
+ def sequence_next(name)
192
+ return storage.sequence_next(schema.sequence(name))
193
+ end
194
+
195
+ ##############################################################
196
+ # Loading methods #
197
+ ##############################################################
198
+
199
+ # Implements the Mapper#count method doing a count SQL query.
200
+ def count(condition_or_query)
201
+ if (condition_or_query.is_a?(Query))
202
+ q = condition_or_query.clone
203
+ else
204
+ q = Query.new(condition_or_query, @model.primary_keys)
205
+ end
206
+ prepare_query(q)
207
+ storage_query = prepare_select(q)
208
+ storage_query[:query_type] = :count
209
+ storage_query.delete(:order)
210
+ storage_query.delete(:limit)
211
+ return @storage.query(storage_query)
212
+ end
213
+
214
+ # Implements the Mapper#fetch method.
215
+ def fetch(query)
216
+ # Spider.logger.debug("Fetching model #{@model} query:")
217
+ # Spider.logger.debug(query)
218
+ storage_query = prepare_select(query)
219
+ if (storage_query)
220
+ result = @storage.query(storage_query)
221
+ result.total_rows = @storage.total_rows if (query.request.total_rows)
222
+ end
223
+ return result
224
+ end
225
+
226
+ # Finds objects by SQL, mapping back the storage result.
227
+ def find_by_sql(sql, *bind_vars)
228
+ result = storage.execute(sql, *bind_vars)
229
+ set = QuerySet.new(@model)
230
+ result.each do |row|
231
+ set << map(nil, row, @model)
232
+ end
233
+ return set
234
+ end
235
+
236
+ # Implements the Mapper#map method.
237
+ # Converts a DB result row to an object.
238
+ def map(request, result, obj)
239
+ if (!request)
240
+ request = Request.new
241
+ @model.elements_array.each{ |el| request.request(el.name) }
242
+ end
243
+ model = obj.is_a?(Class) ? obj : obj.model
244
+ data = {}
245
+ request.keys.each do |element_name|
246
+ element = @model.elements[element_name]
247
+ result_value = nil
248
+ next if !element || element.integrated? || !have_references?(element)
249
+ if (element.model? && schema.has_foreign_fields?(element.name))
250
+ pks = {}
251
+ keys_set = true
252
+ element.model.primary_keys.each do |key|
253
+ key_val = result[schema.foreign_key_field(element_name, key.name).name]
254
+ keys_set = false unless key_val
255
+ pks[key.name] = map_back_value(key.type, key_val)
256
+ end
257
+ # begin
258
+ data[element_name] = keys_set ? Spider::Model.get(element.model, pks) : nil
259
+ # rescue IdentityMapperException
260
+ # null keys, nothing to set
261
+ # end
262
+ elsif !element.model?
263
+ data[element_name] = map_back_value(element.type, result[schema.field(element_name).name])
264
+ end
265
+ end
266
+ begin
267
+ obj = Spider::Model.get(model, data)
268
+ rescue IdentityMapperException => exc
269
+ # This should not happen
270
+ Spider::Logger.warn("Row in DB without primary keys for model #{model}; won't be mapped:")
271
+ Spider::Logger.warn(data)
272
+ return nil
273
+ end
274
+ data.keys.each{ |el| obj.element_loaded(el) }
275
+ if (request.polymorphs)
276
+ request.polymorphs.each do |model, polym_request|
277
+ polym_result = {}
278
+ polym_request.keys.each do |element_name|
279
+ field = model.mapper.schema.field(element_name).name
280
+ res_field = "#{model.mapper.schema.table}_#{field}"
281
+ polym_result[field] = result[res_field] if result[res_field]
282
+ end
283
+ if (!polym_result.empty?)
284
+ polym_obj = model.new
285
+ polym_obj = polym_obj.mapper.map(polym_request, polym_result, polym_obj)
286
+ polym_obj.set_loaded_value(model.extended_models[@model], obj)
287
+ obj = polym_obj
288
+ break
289
+ end
290
+ end
291
+ end
292
+ return obj
293
+ end
294
+
295
+ def prepare_query_request(request, obj=nil) #:nodoc:
296
+ super(request, obj)
297
+ end
298
+
299
+ # Returns true if an element can be loaded joined-in.
300
+ def can_join?(element)
301
+ return false if element.multiple?
302
+ return false if element.storage != @storage
303
+ return true
304
+ end
305
+
306
+ # Generates a select hash description based on the query.
307
+ def prepare_select(query) #:nodoc:
308
+ condition, joins = prepare_condition(query.condition)
309
+ elements = query.request.keys.select{ |k| mapped?(k) }
310
+ keys = []
311
+ primary_keys = []
312
+ types = {}
313
+ if (query.limit && query.order.empty?)
314
+ @model.primary_keys.each do |key|
315
+ elements << key.name unless elements.include?(key.name)
316
+ query.order_by(key.name, :asc)
317
+ end
318
+ end
319
+ order, order_joins = prepare_order(query)
320
+ joins += order_joins if order_joins
321
+ seen_fields = {}
322
+ model_pks = []
323
+ @model.primary_keys.each do |pk|
324
+ if (pk.integrated?)
325
+ model_pks << pk.integrated_from.name
326
+ else
327
+ model_pks << pk.name
328
+ end
329
+ end
330
+ elements.each do |el|
331
+ element = @model.elements[el.to_sym]
332
+ next if !element || !element.type || element.integrated?
333
+ if (!element.model?)
334
+ field = schema.field(el)
335
+ unless seen_fields[field.name]
336
+ keys << field
337
+ primary_keys << field if model_pks.include?(el)
338
+ seen_fields[field.name] = true
339
+ end
340
+ elsif (!element.multiple?)
341
+ if (schema.has_foreign_fields?(el))
342
+ element.model.primary_keys.each do |key|
343
+ field = schema.foreign_key_field(el, key.name)
344
+ unless seen_fields[field.name]
345
+ keys << field
346
+ primary_keys << field if model_pks.include?(el)
347
+ seen_fields[field.name] = true
348
+ end
349
+ end
350
+ end
351
+ sub_request = query.request[element.name]
352
+ # if (can_join?(element) && sub_request.is_a?(Request) &&
353
+ # sub_request.select{|k, v| !element.model.elements[k].primary_key?}.length > 0)
354
+ # sub_request = element.mapper.prepare_query_request(sub_request).reject{ |name, req| element.reverse == name }
355
+ # sub_select = element.mapper.prepare_select(Query.new(nil, sub_request))
356
+ # keys += sub_select[:keys]
357
+ # joins << get_join(element)
358
+ # end
359
+ end
360
+ end
361
+ if (query.request.polymorphs? || !query.condition.polymorphs.empty?)
362
+ only_conditions = {:conj => 'or', :values => []} if (query.request.only_polymorphs?)
363
+ polymorphs = (query.request.polymorphs.keys + query.condition.polymorphs).uniq
364
+ polymorphs.each do |model|
365
+ polym_request = query.request.polymorphs[model] || Request.new
366
+ extension_element = model.extended_models[@model]
367
+ model.mapper.prepare_query_request(polym_request)
368
+ polym_request.reject!{|k, v|
369
+ model.elements[k].integrated? && model.elements[k].integrated_from.name == extension_element
370
+ }
371
+ polym_only = {:conj => 'and', :values => []} if (query.request.only_polymorphs?)
372
+ model.elements_array.select{ |el| el.attributes[:local_pk] }.each do |el|
373
+ polym_request[el.name] = true
374
+ if (query.request.only_polymorphs?)
375
+ polym_only[:values] << [model.mapper.schema.qualified_field(el.name), '<>', nil]
376
+ end
377
+ end
378
+ only_conditions[:values] << polym_only if query.request.only_polymorphs?
379
+ polym_select = model.mapper.prepare_select(Query.new(nil, polym_request)) # FIXME!
380
+ polym_select[:keys].map!{ |key| "#{key} AS #{key.to_s.gsub('.', '_')}"}
381
+ keys += polym_select[:keys]
382
+ join_fields = {}
383
+ @model.primary_keys.each do |key|
384
+ from_field = @schema.field(key.name)
385
+ to_field = model.mapper.schema.foreign_key_field(extension_element, key.name)
386
+ join_fields[from_field] = to_field
387
+ end
388
+ # FIXME: move to get_join
389
+ join = {
390
+ :type => :left,
391
+ :from => @schema.table,
392
+ :to => model.mapper.schema.table,
393
+ :keys => join_fields
394
+ }
395
+ joins << join
396
+ end
397
+
398
+ end
399
+ if (only_conditions)
400
+ if (condition[:conj].downcase != 'and')
401
+ condition = {:conj => 'and', :values => [condition]}
402
+ end
403
+ condition[:values] << only_conditions
404
+ end
405
+ tables = [schema.table]
406
+ joins = prepare_joins(joins)
407
+ return nil if (keys.empty?)
408
+ return {
409
+ :query_type => :select,
410
+ :keys => keys,
411
+ :primary_keys => primary_keys,
412
+ :tables => tables,
413
+ :condition => condition,
414
+ :joins => joins,
415
+ :order => order,
416
+ :offset => query.offset,
417
+ :limit => query.limit
418
+ }
419
+ end
420
+
421
+ #--
422
+ # FIXME: document
423
+ def prepare_joins(joins) # :nodoc:
424
+ h = {}
425
+ joins.each do |join|
426
+ h[join[:from]] ||= {}
427
+ cur = (h[join[:from]][join[:to]] ||= [])
428
+ has_join = false
429
+ cur.each do |cur_join|
430
+ if (cur_join[:keys] == join[:keys] && cur_join[:conditions] == join[:conditions])
431
+ has_join = true
432
+ break
433
+ end
434
+ end
435
+ h[join[:from]][join[:to]] << join unless has_join
436
+ end
437
+ return h
438
+ end
439
+
440
+
441
+ # Generates a storage description for the condition
442
+ # Returns a list of three elements, composed of
443
+ # * conditions: an hash
444
+ # {
445
+ # :conj => 'and'|'or',
446
+ # :values => an array of [field, comparison, value] triplets
447
+ # }
448
+ # * joins: an array of structures as returned by #get_join
449
+ # * remaining_condition: part of the condition which can't be passed to the storage
450
+ #--
451
+ # TODO: better name for :values
452
+ def prepare_condition(condition, options={})
453
+ # FIXME: move to mapper
454
+ model = condition.polymorph ? condition.polymorph : @model
455
+ model_schema = model.mapper.schema
456
+ # debugger if condition.polymorph
457
+ condition.each_with_comparison do |k, v, comp|
458
+ # normalize condition values
459
+ element = model.elements[k.to_sym]
460
+ if (!v.is_a?(Condition) && element.model?)
461
+ condition.delete(element.name)
462
+ if (v.is_a?(BaseModel))
463
+ element.model.primary_keys.each do |primary_key|
464
+ condition.set("#{element.name}.#{primary_key.name}", '=', v.get(primary_key))
465
+ end
466
+ elsif (element.model.primary_keys.length == 1 )
467
+ new_v = Condition.new
468
+ if (model.mapper.have_references?(element.name))
469
+ new_v.set(element.model.primary_keys[0].name, comp, v)
470
+ else
471
+ new_v.set(element.reverse, comp, v)
472
+ end
473
+ condition.set(element.name, comp, new_v)
474
+ else
475
+ raise MapperError, "Value condition passed on #{k}, but #{element.model} has more then one primary key"
476
+ end
477
+ end
478
+ end
479
+ bind_values = []
480
+ joins = []
481
+ cond = {}
482
+ remaining_condition = Condition.new # TODO: implement
483
+ cond[:conj] = condition.conjunction.to_s
484
+ cond[:values] = []
485
+ # FIXME: the allow_left_joins hack will probably not work in the general case
486
+ cond[:allow_left_joins] = options[:allow_left_joins] || {}
487
+ condition.each_with_comparison do |k, v, comp|
488
+ element = model.elements[k.to_sym]
489
+ next unless model.mapper.mapped?(element)
490
+ if (element.model?)
491
+ if (model.mapper.have_references?(element.name) && v.select{ |key, value| !element.model.elements[key].primary_key? }.empty?)
492
+ # 1/n <-> 1 with only primary keys
493
+ element_cond = {:conj => 'AND', :values => []}
494
+ v.each_with_comparison do |el_k, el_v, el_comp|
495
+ field = model_schema.qualified_foreign_key_field(element.name, el_k)
496
+ el_comp ||= '='
497
+ op = el_comp
498
+ field_cond = [field, op, map_condition_value(element.model.elements[el_k.to_sym].type, el_v)]
499
+ element_cond[:values] << field_cond
500
+ if (el_v.nil? && el_comp == '=')
501
+ cond[:allow_left_joins][element.model] = true
502
+ end
503
+ end
504
+ cond[:values] << element_cond
505
+ else
506
+ if (element.storage == model.mapper.storage)
507
+ join_type = cond[:allow_left_joins][element.model] ? :left : :inner
508
+ sub_join = model.mapper.get_join(element, join_type)
509
+ joins << sub_join
510
+ element.model.mapper.prepare_query_condition(v)
511
+
512
+ sub_condition, sub_joins = element.mapper.prepare_condition(v, :table => sub_join[:as], :allow_left_joins => cond[:allow_left_joins])
513
+ sub_condition[:table] = sub_join[:as] if sub_join[:as]
514
+ joins += sub_joins
515
+
516
+ cond[:values] << sub_condition
517
+ cond[:allow_left_joins].merge!(sub_condition[:allow_left_joins])
518
+ else
519
+ remaining_condition ||= Condition.new
520
+ remaining_condition.set(k, comp, v)
521
+ end
522
+ end
523
+ elsif(model_schema.field(element.name))
524
+ field = model_schema.qualified_field(element.name, options[:table])
525
+ op = comp ? comp : '='
526
+ if (v.is_a?(Spider::QueryFuncs::Expression))
527
+ v_joins = prepare_expression(v)
528
+ joins += v_joins
529
+ cond[:values] << [field, op, v]
530
+ else
531
+ cond[:values] << [field, op, map_condition_value(model.elements[k.to_sym].type, v)]
532
+ end
533
+ end
534
+
535
+ end
536
+ sub_sqls = []
537
+ sub_bind_values = []
538
+ condition.subconditions.each do |sub|
539
+ sub_res = self.prepare_condition(sub, :allow_left_joins => cond[:allow_left_joins])
540
+ cond[:values] << sub_res[0]
541
+ joins += sub_res[1]
542
+ remaining_condition += sub_res[2]
543
+ end
544
+ return [cond, joins, remaining_condition]
545
+ end
546
+
547
+ # Figures out a join for element. Returns join hash description, i.e. :
548
+ # join = {
549
+ # :type => :inner|:outer|...,
550
+ # :from => 'table1',
551
+ # :to => 'table2',
552
+ # :keys => hash of key pairs,
553
+ # :condition => join condition
554
+ # }
555
+ def get_join(element, join_type = :inner)
556
+ return unless element.model?
557
+ Spider::Logger.debug("Getting join for model #{@model} to element #{element}")
558
+ Spider::Logger.debug(@model.primary_keys.map{|k| k.name})
559
+ element_table = element.mapper.schema.table
560
+ if (schema.has_foreign_fields?(element.name))
561
+ Spider::Logger.debug("JOIN A from #{@model} to #{element.name}")
562
+ keys = {}
563
+ element.model.primary_keys.each do |key|
564
+ if (key.integrated?)
565
+ # FIXME
566
+ raise "Unimplemented join dereference for multiple primary keys" if key.integrated_from.model.primary_keys.length > 1
567
+ el_field = element.mapper.schema.foreign_key_field(key.integrated_from.name, key.integrated_from.model.primary_keys[0].name)
568
+ else
569
+ el_field = element.mapper.schema.field(key.name)
570
+ end
571
+ keys[schema.foreign_key_field(element.name, key.name)] = el_field
572
+ # FIXME: works with models as primary keys through a hack in the field method of db_schema,
573
+ # assuming the model has only one key. the correct way would be to get another join
574
+ end
575
+ if (element.condition)
576
+ condition, condition_joins, condition_remaining = element.mapper.prepare_condition(element.condition)
577
+ end
578
+ as = nil
579
+ if (element.model == @model)
580
+ as = "#{schema.table}_#{element.name}"
581
+ end
582
+ join = {
583
+ :type => join_type,
584
+ :from => schema.table,
585
+ :to => element.mapper.schema.table,
586
+ :keys => keys,
587
+ :condition => condition,
588
+ :as => as
589
+ }
590
+ elsif (element.has_single_reverse? && element.mapper.schema.has_foreign_fields?(element.reverse)) # n/1 <-> n
591
+ Spider::Logger.debug("JOIN B from #{@model} to #{element.name}")
592
+ keys = {}
593
+ @model.primary_keys.each do |key|
594
+ our_field = nil
595
+ if (key.integrated?)
596
+ our_field = schema.foreign_key_field(key.integrated_from.name, key.integrated_from_element)
597
+ else
598
+ our_field = schema.field(key.name)
599
+ end
600
+ keys[our_field] = element.mapper.schema.foreign_key_field(element.reverse, key.name)
601
+ end
602
+ if (element.condition)
603
+ condition, condition_joins, condition_remaining = element.mapper.prepare_condition(element.condition)
604
+ end
605
+ join = {
606
+ :type => :inner,
607
+ :from => schema.table,
608
+ :to => element.mapper.schema.table,
609
+ :keys => keys,
610
+ :condition => condition
611
+ }
612
+ else # n <-> n
613
+ # no need to handle n <-> n
614
+ end
615
+ # FIXME: add element conditions!
616
+ return join
617
+ end
618
+
619
+ # Returns the joins needed for an element down the tree, expressed in dotted notation.
620
+ # Returns a triplet composed of
621
+ # * joins
622
+ # * final model called
623
+ # * final element called
624
+ def get_deep_join(dotted_element)
625
+ #return [[], @model, @model.elements[dotted_element]] unless dotted_element.is_a?(String)
626
+ parts = dotted_element.to_s.split('.').map{ |el| el.to_sym }
627
+ current_model = @model
628
+ joins = []
629
+ el = nil
630
+ Spider::Logger.debug("GETTING DEEP JOIN TO #{dotted_element} (#{@model})")
631
+ parts.each do |part|
632
+ el = current_model.elements[part]
633
+ if (el.integrated?)
634
+ joins << current_model.mapper.get_join(el.integrated_from)
635
+ current_model = el.integrated_from.type
636
+ el = current_model.elements[el.integrated_from_element]
637
+ end
638
+ if (el.model?) # && can_join?(el)
639
+ joins << current_model.mapper.get_join(el)
640
+ current_model = el.model
641
+ end
642
+ end
643
+ while (el.integrated?)
644
+ joins << current_model.mapper.get_join(el.integrated_from)
645
+ # joins << current_model.integrated_from.mapper.get_join(el.integrated_from_element)
646
+ current_model = el.integrated_from.type
647
+ el = current_model.elements[el.integrated_from_element]
648
+ end
649
+ return [joins, current_model, el]
650
+ end
651
+
652
+ # Takes a Spider::QueryFuncs::Expression, and associates the fields to the corresponding elements
653
+ # Returns an array of needed joins
654
+ def prepare_expression(expr)
655
+ joins = []
656
+ expr.each_element do |v_el|
657
+ v_joins, j_model, j_el = get_deep_join(v_el)
658
+ db_field = j_model.mapper.schema.qualified_field(j_el.name)
659
+ joins += v_joins
660
+ expr[v_el] = db_field
661
+ end
662
+ return joins
663
+ end
664
+
665
+ # Returns a pair composed of
666
+ # * fields, an array of [field, direction] couples; and
667
+ # * joins, joins needed for the order, if any
668
+ def prepare_order(query)
669
+ joins = []
670
+ fields = []
671
+ query.order.each do |order|
672
+ order_element, direction = order
673
+ el_model = @model
674
+ if (order_element.is_a?(QueryFuncs::Function))
675
+ func_fields = []
676
+ func_elements = order_element.inner_elements
677
+ func_elements.each do |el_name, owner_func|
678
+ el_joins, el_model, el = get_deep_join(el_name)
679
+ joins += el_joins
680
+ owner_func.mapper_fields ||= {}
681
+ owner_func.mapper_fields[el.name] = el_model.mapper.schema.field(el.name)
682
+ end
683
+ field = storage.function(order_element)
684
+ fields << [field, direction]
685
+ else
686
+ el_joins, el_model, el = get_deep_join(order_element)
687
+ if (el.model?)
688
+ # FIXME: integrated elements
689
+ el.model.primary_keys.each do |pk|
690
+ fields << [el.model.mapper.schema.field(pk.name), direction]
691
+ end
692
+ else
693
+ field = el_model.mapper.schema.field(el.name)
694
+ fields << [field, direction]
695
+ end
696
+ joins += el_joins
697
+ end
698
+ end
699
+ return [fields, joins]
700
+ end
701
+
702
+ # Returns a type accepted by the storage for type.
703
+ def map_type(type)
704
+ st = type
705
+ while (st && !storage.class.base_types.include?(st))
706
+ st = Model.simplify_type(st)
707
+ end
708
+ return type unless st
709
+ return st
710
+ end
711
+
712
+ # Converts a value in one accepted by the storage.
713
+ def map_value(type, value, mode=nil)
714
+ return value if value.nil?
715
+ if (type < Spider::DataType && value)
716
+ value = type.from_value(value) unless value.is_a?(type)
717
+ value = value.map(self.type)
718
+ elsif type.class == Class && type.subclass_of?(Spider::Model::BaseModel)
719
+ value = type.primary_keys.map{ |key| value.send(key.name) }
720
+ else
721
+ case type.name
722
+ when 'Spider::DataTypes::Bool'
723
+ value = value ? 1 : 0
724
+ end
725
+ end
726
+ return value
727
+ end
728
+
729
+ # Prepares a value going to be bound to an insert or update statement
730
+ def map_save_value(type, value, save_mode)
731
+ value = map_value(type, value, :save)
732
+ return @storage.value_for_save(Model.simplify_type(type), value, save_mode)
733
+ end
734
+
735
+ # Prepares a value for a condition.
736
+ def map_condition_value(type, value)
737
+ if value.is_a?(Range)
738
+ return Range.new(map_condition_value(type, value.first), map_condition_value(type, value.last))
739
+ end
740
+ return value if ( type.class == Class && type.subclass_of?(Spider::Model::BaseModel) )
741
+ value = map_value(type, value, :condition)
742
+ return @storage.value_for_condition(Model.simplify_type(type), value)
743
+ end
744
+
745
+ # Converts a storage value back to the corresponding base type or DataType.
746
+ def map_back_value(type, value)
747
+ value = value[0] if value.class == Array
748
+ value = storage.value_to_mapper(Model.simplify_type(type), value)
749
+ if (type < Spider::DataType && type.maps_back_to)
750
+ type = type.maps_back_to
751
+ end
752
+ case type.name
753
+ when 'Fixnum'
754
+ return value ? value.to_i : nil
755
+ when 'Float'
756
+ return value ? value.to_f : nil
757
+ when 'Spider::DataTypes::Bool'
758
+ return value == 1 ? true : false
759
+ end
760
+ return nil unless value
761
+ case type.name
762
+ when 'Date', 'DateTime'
763
+ return type.parse(value) unless value.is_a?(Date)
764
+ end
765
+ if (type < Spider::DataType)
766
+ value = type.from_value(value)
767
+ end
768
+ return value
769
+ end
770
+
771
+ ##############################################################
772
+ # Primary keys #
773
+ ##############################################################
774
+
775
+ # Empty hook to set primary keys in the model before insert. Override if needed.
776
+ def assign_primary_keys(obj)
777
+ # may be implemented in model through the 'with_mapper' method
778
+ end
779
+
780
+
781
+ ##############################################################
782
+ # Storage strategy #
783
+ ##############################################################
784
+
785
+ # UnitOfWork dependencies.
786
+ def get_dependencies(obj, action)
787
+ deps = []
788
+ task = MapperTask.new(obj, action)
789
+ deps = []
790
+ case action
791
+ when :keys
792
+ deps << [task, MapperTask.new(obj, :save)] unless obj.primary_keys_set? || (!obj.mapper || !obj.mapper.class.write?)
793
+ when :save
794
+ elements = @model.elements.select{ |n, el| el.model? && obj.element_has_value?(el) && obj.element_modified?(el)}
795
+ # n <-> n and n|1 <-> 1
796
+ elements.select{ |n, el| !el.has_single_reverse? }.each do |name, element|
797
+ if (element.multiple?)
798
+ set = obj.send(element.name)
799
+ set.each do |set_obj|
800
+ deps << [task, MapperTask.new(set_obj, :keys)]
801
+ end
802
+ else
803
+ deps << [task, MapperTask.new(obj.send(element.name), :keys)]
804
+ end
805
+ end
806
+ elements.select{ |n, el| el.multiple? && el.has_single_reverse? }.each do |name, element|
807
+ if (element.model? && element.type.mapper && element.type.mapper.class.write?)
808
+ set = obj.send(element.name)
809
+ set.each do |set_obj|
810
+ sub_task = MapperTask.new(set_obj, :save)
811
+ deps << [sub_task, MapperTask.new(obj, :keys)]
812
+ end
813
+ end
814
+ end
815
+ end
816
+ return deps
817
+ end
818
+
819
+
820
+ ##############################################################
821
+ # Schema management #
822
+ ##############################################################
823
+
824
+ # Extend schema. Given block will be instance_eval'd after schema auto generation.
825
+ # See also #define_schema.
826
+ def with_schema(*params, &proc)
827
+ @schema_proc = proc
828
+ end
829
+
830
+ # Define schema. Given block will be instance_eval'd before schema auto generation.
831
+ # See also #with_schema.
832
+ def define_schema(*params, &proc)
833
+ @schema_define_proc = proc
834
+ end
835
+
836
+ # Returns @schema, or creates one.
837
+ def schema
838
+ @schema ||= get_schema()
839
+ return @schema
840
+ end
841
+
842
+ # Returns the schema, as defined or autogenerated.
843
+ def get_schema
844
+ schema = @model.superclass.mapper.get_schema() if (@model.attributes[:inherit_storage])
845
+ if (@schema_define_proc)
846
+ schema = DbSchema.new
847
+ schema.instance_eval(&@schema_define_proc)
848
+ end
849
+ schema = generate_schema(schema)
850
+ if (@schema_proc)
851
+ schema.instance_eval(&@schema_proc)
852
+ end
853
+ return schema
854
+ end
855
+
856
+ # Autogenerates schema. Returns a DbSchema.
857
+ def generate_schema(schema=nil)
858
+ had_schema = schema ? true : false
859
+ schema ||= DbSchema.new
860
+ n = @model.name.sub('::Models', '')
861
+ n.sub!(@model.app.name, @model.app.short_prefix) if @model.app.short_prefix
862
+ schema.table ||= @model.attributes[:db_table] || @storage.table_name(n)
863
+ integrated_pks = []
864
+ @model.each_element do |element|
865
+ if element.integrated?
866
+ integrated_pks << [element.integrated_from.name, element.integrated_from_element] if (element.primary_key?)
867
+ end
868
+ end
869
+ @model.each_element do |element|
870
+ next if element.integrated?
871
+ next unless mapped?(element)
872
+ next if had_schema && schema.pass[element.name]
873
+ next if element.attributes[:added_reverse] && element.has_single_reverse?
874
+ if (!element.model?)
875
+ column = schema.columns[element.name]
876
+ storage_type = Spider::Model.base_type(element.type)
877
+ db_attributes = column.attributes if column
878
+ if (!db_attributes || db_attributes.empty?)
879
+ db_attributes = @storage.column_attributes(storage_type, element.attributes)
880
+ db_attributes.merge(element.attributes[:db]) if (element.attributes[:db])
881
+ if (element.attributes[:autoincrement] && !db_attributes[:autoincrement])
882
+ schema.set_sequence(element.name, @storage.sequence_name("#{schema.table}_#{element.name}"))
883
+ end
884
+ end
885
+ column_type = element.attributes[:db_column_type] || @storage.column_type(storage_type, element.attributes)
886
+ unless column
887
+ column_name = element.attributes[:db_column_name] || @storage.column_name(element.name)
888
+ column = Field.new(schema.table, column_name, column_type)
889
+ end
890
+ column.type ||= column_type
891
+ column.attributes = db_attributes
892
+ column.primary_key = true if element.primary_key?
893
+ schema.set_column(element.name, column)
894
+ elsif (true) # FIXME: must have condition element.storage == @storage in some of the subcases
895
+ if (!element.multiple?) # 1/n <-> 1
896
+ current_schema = schema.foreign_keys[element.name] || {}
897
+ foreign_key_constraints = {}
898
+ element.type.primary_keys.each do |key|
899
+ if key.model? # fixme: only works with single primary key model (after the first)
900
+ curr_key = key
901
+ curr_key = curr_key.model.primary_keys[0] while curr_key.model? && curr_key.model.primary_keys.length == 1
902
+ next if curr_key.model
903
+ key_type = curr_key.type
904
+ key_attributes = curr_key.attributes
905
+ else
906
+ key_type = key.type
907
+ key_attributes = key.attributes
908
+ end
909
+ #key_column = element.mapper.schema.column(key.name)
910
+
911
+ key_attributes = {
912
+ :length => key_attributes[:length],
913
+ :precision => key_attributes[:precision]
914
+ }
915
+ column = current_schema[key.name]
916
+ column_type = element.attributes[:db_column_type] || @storage.column_type(key_type, key_attributes)
917
+ unless column
918
+ column_name = element.attributes[:db_column_name] || @storage.column_name("#{element.name}_#{key.name}")
919
+ column_attributes = @storage.column_attributes(key_type, key_attributes)
920
+ column = Field.new(schema.table, column_name, column_type, column_attributes)
921
+ end
922
+ column.type ||= column_type
923
+ column.primary_key = true if (element.primary_key? || integrated_pks.include?([element.name, key.name]))
924
+ schema.set_foreign_key(element.name, key.name, column)
925
+ end
926
+
927
+ end
928
+ end
929
+ end
930
+ @model.sequences.each do |name|
931
+ schema.set_sequence(name, @storage.sequence_name("#{schema.table}_#{name}"))
932
+ end
933
+ return schema
934
+ end
935
+
936
+ def compute_foreign_key_constraints
937
+ @model.each_element do |element|
938
+ foreign_key_constraints = {}
939
+ next if element.integrated?
940
+ next unless mapped?(element)
941
+ next if element.attributes[:added_reverse] && element.has_single_reverse?
942
+ next unless element.model?
943
+ next if element.multiple?
944
+ next unless element.type.mapper.storage == @storage
945
+ element.type.primary_keys.each do |key|
946
+ column = self.schema.foreign_key_field(element.name, key.name)
947
+ column_name = column.name
948
+ next if !key.integrated? && !element.type.mapper.schema.column(key.name) # FIXME
949
+ foreign_key_constraints[column_name] = key.integrated? ? \
950
+ element.type.mapper.schema.foreign_key_field(key.integrated_from.name, key.integrated_from_element).name : \
951
+ element.type.mapper.schema.column(key.name).name
952
+ end
953
+ unless foreign_key_constraints.empty?
954
+ name = element.attributes[:db_foreign_key_name] || "FK_#{schema.table.name}_#{element.name}"
955
+ self.schema.set_foreign_key_constraint(name, element.type.mapper.schema.table.name, foreign_key_constraints)
956
+ end
957
+ end
958
+ end
959
+
960
+ # Returns an array of all keys, "dereferencing" model keys.
961
+ def collect_real_keys(element, path=[]) # :nodoc:
962
+ real_keys = []
963
+ element.type.primary_keys.each do |key|
964
+ if (key.model?)
965
+ real_keys += schema_collect_real_keys(key, path<<element.name)
966
+ else
967
+ real_keys << [key, path<<element.name]
968
+ end
969
+ end
970
+ return real_keys
971
+ end
972
+
973
+ # Modifies the storage according to the schema.
974
+ def sync_schema(force=false, options={})
975
+ compute_foreign_key_constraints
976
+ schema_description = schema.get_schemas
977
+ sequences = {}
978
+ sequences[schema.table] = schema.sequences
979
+
980
+ @model.elements_array.select{ |el| el.attributes[:anonymous_model] }.each do |el|
981
+ next if el.model.mapper.class != self.class
982
+ el.model.mapper.compute_foreign_key_constraints
983
+ schema_description.merge!(el.model.mapper.schema.get_schemas)
984
+ sequences[el.model.mapper.schema.table] ||= {}
985
+ sequences[el.model.mapper.schema.table].merge!(el.model.mapper.schema.sequences)
986
+ # Spider::Logger.debug("MERGING SEQUENCES:")
987
+ # Spider::Logger.debug(el.model.mapper.schema.sequences)
988
+ # sequences.merge!(el.model.mapper.schema.sequences)
989
+ end
990
+ schema_description.each do |table_name, table_schema|
991
+ table_attributes = {
992
+ :primary_keys => table_schema[:attributes][:primary_keys]
993
+ }
994
+ unless options[:no_foreign_key_constraints]
995
+ table_attributes[:foreign_key_constraints] = table_schema[:attributes][:foreign_key_constraints] || []
996
+ end
997
+ if @storage.table_exists?(table_name)
998
+ alter_table(table_name, table_schema[:columns], table_attributes, force)
999
+ else
1000
+ create_table(table_name, table_schema[:columns], table_attributes)
1001
+ end
1002
+ if (options[:drop_fields])
1003
+ current = @storage.describe_table(table_name)[:columns]
1004
+ current.each_key do |cur|
1005
+ @storage.drop_field(table_name, cur) if (!table_schema[:columns][cur])
1006
+ end
1007
+ end
1008
+ end
1009
+ seen = {}
1010
+ sequences.each do |sequence_table, table_sequences|
1011
+ table_sequences.each do |element_name, db_name|
1012
+ next if seen[db_name]
1013
+ if storage.sequence_exists?(db_name)
1014
+ if (options[:update_sequences])
1015
+ sql = "SELECT MAX(#{schema.field(element_name).name}) AS M FROM #{sequence_table}"
1016
+ res = @storage.execute(sql)
1017
+ max = res[0]['M'].to_i
1018
+ storage.update_sequence(db_name, max+1)
1019
+ end
1020
+ else
1021
+ storage.create_sequence(db_name)
1022
+ end
1023
+ seen[db_name] = true
1024
+ end
1025
+ end
1026
+ end
1027
+
1028
+ # Returns a create table structure description.
1029
+ def create_table(table_name, fields, attributes) # :nodoc:
1030
+ fields = fields.map{ |name, details| {
1031
+ :name => name,
1032
+ :type => details[:type],
1033
+ :attributes => details[:attributes]
1034
+ } }
1035
+ @storage.create_table({
1036
+ :table => table_name,
1037
+ :fields => fields,
1038
+ :attributes => attributes,
1039
+ })
1040
+ end
1041
+
1042
+ # Returns an alter table structure description
1043
+ def alter_table(name, fields, attributes, force=nil) # :nodoc:
1044
+ current = @storage.describe_table(name)
1045
+ current_fields = current[:columns]
1046
+ add_fields = []
1047
+ alter_fields = []
1048
+ all_fields = []
1049
+ unsafe = []
1050
+ fields.each_key do |field|
1051
+ field_hash = {
1052
+ :name => field,
1053
+ :type => fields[field][:type],
1054
+ :attributes => fields[field][:attributes]
1055
+ }
1056
+ all_fields << field_hash
1057
+ if (!current_fields[field])
1058
+ add_fields << field_hash
1059
+ else
1060
+ type = fields[field][:type]
1061
+ field_attributes = fields[field][:attributes]
1062
+ field_attributes ||= {}
1063
+ if (!@storage.schema_field_equal?(current_fields[field], fields[field]))
1064
+ Spider.logger.debug("DIFFERENT: #{field}")
1065
+ Spider.logger.debug(current_fields[field])
1066
+ Spider.logger.debug(fields[field])
1067
+ unless @storage.safe_schema_conversion?(current_fields[field], fields[field]) || force
1068
+ unsafe << field
1069
+ end
1070
+ alter_fields << field_hash
1071
+ end
1072
+ end
1073
+ raise SchemaSyncUnsafeConversion.new(unsafe) unless unsafe.empty?
1074
+ end
1075
+ alter_attributes = {}
1076
+ if (current[:primary_keys] != attributes[:primary_keys])
1077
+ alter_attributes[:primary_keys] = attributes[:primary_keys]
1078
+ end
1079
+ if (attributes[:foreign_key_constraints])
1080
+
1081
+ end
1082
+ alter_attributes[:foreign_key_constraints] = attributes[:foreign_key_constraints]
1083
+ @storage.alter_table({
1084
+ :table => name,
1085
+ :add_fields => add_fields,
1086
+ :alter_fields => alter_fields,
1087
+ :all_fields => all_fields,
1088
+ :attributes => alter_attributes,
1089
+ :current => current
1090
+ })
1091
+ end
1092
+
1093
+ ##############################################################
1094
+ # Aggregates #
1095
+ ##############################################################
1096
+
1097
+ def max(element, condition=nil)
1098
+ element = @model.elements[element] if element.is_a?(Symbol)
1099
+ schema = element.integrated? ? @model.elements[element.integrated_from.name].model.mapper.schema : self.schema
1100
+ max = {}
1101
+ max[:condition], joins = prepare_condition(condition) if condition
1102
+ max[:tables] = [schema.table]
1103
+ max[:field] = schema.field(element.name)
1104
+ joins ||= []
1105
+ max[:joins] = prepare_joins(joins)
1106
+ sql, values = storage.sql_max(max)
1107
+ res = storage.execute(sql, *values)
1108
+ return res[0] && res[0]['M'] ? res[0]['M'] : 0
1109
+ end
1110
+
1111
+
1112
+ end
1113
+
1114
+ # Error raised when a conversion results in a potential data loss.
1115
+
1116
+ class SchemaSyncUnsafeConversion < RuntimeError
1117
+ attr :fields
1118
+ def initialize(fields)
1119
+ @fields = fields
1120
+ end
1121
+ def to_s
1122
+ "Unsafe conversion on fields #{fields.join(', ')}"
1123
+ end
1124
+ end
1125
+
1126
+ end; end; end