spiderfw 0.5

Sign up to get free protection for your applications and to get access to all the features.
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