ribit 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (650) hide show
  1. data/INSTALL +52 -0
  2. data/LICENSE +343 -0
  3. data/README +42 -0
  4. data/bin/ribit +26 -0
  5. data/bin/ribit-setup +153 -0
  6. data/bin/ribitd +18 -0
  7. data/doc/TODO.txt +207 -0
  8. data/doc/devdiary.txt +258 -0
  9. data/doc/diagrams/content-classes.dia +0 -0
  10. data/doc/diagrams/main-classes.dia +0 -0
  11. data/doc/diagrams/page-rendering-classes.dia +0 -0
  12. data/doc/diagrams/ribitservlet-classes.dia +0 -0
  13. data/doc/examples/xhtml-example.html +64 -0
  14. data/doc/notes.txt +7 -0
  15. data/doc/rdoc/classes/ActionAdapter.html +137 -0
  16. data/doc/rdoc/classes/ActionAdapter.src/M000160.html +26 -0
  17. data/doc/rdoc/classes/ActionElement.html +179 -0
  18. data/doc/rdoc/classes/ActionElement.src/M000204.html +19 -0
  19. data/doc/rdoc/classes/ActionElement.src/M000205.html +18 -0
  20. data/doc/rdoc/classes/ActionManager.html +187 -0
  21. data/doc/rdoc/classes/ActionManager.src/M000237.html +19 -0
  22. data/doc/rdoc/classes/ActionManager.src/M000238.html +22 -0
  23. data/doc/rdoc/classes/ActionManager.src/M000239.html +22 -0
  24. data/doc/rdoc/classes/ActionManager.src/M000240.html +23 -0
  25. data/doc/rdoc/classes/Assert.html +229 -0
  26. data/doc/rdoc/classes/Assert.src/M000369.html +20 -0
  27. data/doc/rdoc/classes/Assert.src/M000370.html +18 -0
  28. data/doc/rdoc/classes/Assert.src/M000371.html +20 -0
  29. data/doc/rdoc/classes/Assert.src/M000372.html +18 -0
  30. data/doc/rdoc/classes/Assert.src/M000373.html +20 -0
  31. data/doc/rdoc/classes/Assert.src/M000374.html +18 -0
  32. data/doc/rdoc/classes/Assert.src/M000375.html +22 -0
  33. data/doc/rdoc/classes/Assert/AssertionFailedException.html +117 -0
  34. data/doc/rdoc/classes/BaseTag.html +166 -0
  35. data/doc/rdoc/classes/BaseTag.src/M000049.html +20 -0
  36. data/doc/rdoc/classes/BoldContainer.html +139 -0
  37. data/doc/rdoc/classes/BoldContainer.src/M000164.html +18 -0
  38. data/doc/rdoc/classes/BoldParser.html +156 -0
  39. data/doc/rdoc/classes/BoldParser.src/M000247.html +18 -0
  40. data/doc/rdoc/classes/BoldParser.src/M000248.html +18 -0
  41. data/doc/rdoc/classes/CachedPage.html +187 -0
  42. data/doc/rdoc/classes/CachedPage.src/M000244.html +20 -0
  43. data/doc/rdoc/classes/CachedPage.src/M000245.html +27 -0
  44. data/doc/rdoc/classes/CachedPage.src/M000246.html +18 -0
  45. data/doc/rdoc/classes/CancelAction.html +179 -0
  46. data/doc/rdoc/classes/CancelAction.src/M000165.html +22 -0
  47. data/doc/rdoc/classes/CancelAction.src/M000166.html +20 -0
  48. data/doc/rdoc/classes/CancelAction.src/M000167.html +21 -0
  49. data/doc/rdoc/classes/CancelCategoryAction.html +164 -0
  50. data/doc/rdoc/classes/CancelCategoryAction.src/M000115.html +22 -0
  51. data/doc/rdoc/classes/CancelCategoryAction.src/M000116.html +20 -0
  52. data/doc/rdoc/classes/CategoriesPage.html +212 -0
  53. data/doc/rdoc/classes/CategoriesPage.src/M000232.html +27 -0
  54. data/doc/rdoc/classes/CategoriesPage.src/M000233.html +18 -0
  55. data/doc/rdoc/classes/CategoriesPage.src/M000234.html +73 -0
  56. data/doc/rdoc/classes/CategoriesPage.src/M000235.html +29 -0
  57. data/doc/rdoc/classes/CategoriesPage.src/M000236.html +59 -0
  58. data/doc/rdoc/classes/CategoryBarActionElement.html +139 -0
  59. data/doc/rdoc/classes/CategoryBarActionElement.src/M000069.html +18 -0
  60. data/doc/rdoc/classes/CategoryBarNextLevelActionElement.html +139 -0
  61. data/doc/rdoc/classes/CategoryBarNextLevelActionElement.src/M000026.html +18 -0
  62. data/doc/rdoc/classes/CategoryFormAction.html +169 -0
  63. data/doc/rdoc/classes/CategoryFormAction.src/M000148.html +18 -0
  64. data/doc/rdoc/classes/CategoryFormAction.src/M000149.html +30 -0
  65. data/doc/rdoc/classes/CategoryFormActionAdapter.html +171 -0
  66. data/doc/rdoc/classes/CategoryFormActionAdapter.src/M000112.html +19 -0
  67. data/doc/rdoc/classes/CategoryFormActionAdapter.src/M000113.html +18 -0
  68. data/doc/rdoc/classes/CategoryFormActionAdapter.src/M000114.html +18 -0
  69. data/doc/rdoc/classes/CompositeAction.html +186 -0
  70. data/doc/rdoc/classes/CompositeAction.src/M000119.html +19 -0
  71. data/doc/rdoc/classes/CompositeAction.src/M000120.html +18 -0
  72. data/doc/rdoc/classes/CompositeAction.src/M000121.html +21 -0
  73. data/doc/rdoc/classes/CompositeAction.src/M000122.html +18 -0
  74. data/doc/rdoc/classes/CompositeLinkActionElement.html +156 -0
  75. data/doc/rdoc/classes/CompositeLinkActionElement.src/M000196.html +20 -0
  76. data/doc/rdoc/classes/CompositeLinkActionElement.src/M000197.html +41 -0
  77. data/doc/rdoc/classes/Constants.html +198 -0
  78. data/doc/rdoc/classes/Container.html +281 -0
  79. data/doc/rdoc/classes/Container.src/M000251.html +19 -0
  80. data/doc/rdoc/classes/Container.src/M000252.html +18 -0
  81. data/doc/rdoc/classes/Container.src/M000253.html +18 -0
  82. data/doc/rdoc/classes/Container.src/M000254.html +18 -0
  83. data/doc/rdoc/classes/Container.src/M000255.html +27 -0
  84. data/doc/rdoc/classes/Container.src/M000256.html +18 -0
  85. data/doc/rdoc/classes/Container.src/M000257.html +18 -0
  86. data/doc/rdoc/classes/Container.src/M000258.html +18 -0
  87. data/doc/rdoc/classes/Container.src/M000259.html +18 -0
  88. data/doc/rdoc/classes/Container.src/M000260.html +23 -0
  89. data/doc/rdoc/classes/ContentDoc.html +236 -0
  90. data/doc/rdoc/classes/ContentDoc.src/M000129.html +22 -0
  91. data/doc/rdoc/classes/ContentDoc.src/M000130.html +18 -0
  92. data/doc/rdoc/classes/ContentDoc.src/M000131.html +20 -0
  93. data/doc/rdoc/classes/ContentDoc.src/M000132.html +18 -0
  94. data/doc/rdoc/classes/ContentDoc.src/M000133.html +18 -0
  95. data/doc/rdoc/classes/ContentDoc.src/M000134.html +18 -0
  96. data/doc/rdoc/classes/ContentDoc.src/M000135.html +18 -0
  97. data/doc/rdoc/classes/ContentParser.html +176 -0
  98. data/doc/rdoc/classes/ContentParser.src/M000176.html +30 -0
  99. data/doc/rdoc/classes/ContentParser.src/M000177.html +28 -0
  100. data/doc/rdoc/classes/ContentParser.src/M000178.html +55 -0
  101. data/doc/rdoc/classes/CurrentList.html +209 -0
  102. data/doc/rdoc/classes/CurrentList.src/M000228.html +19 -0
  103. data/doc/rdoc/classes/CurrentList.src/M000229.html +18 -0
  104. data/doc/rdoc/classes/CurrentList.src/M000230.html +18 -0
  105. data/doc/rdoc/classes/CurrentList.src/M000231.html +18 -0
  106. data/doc/rdoc/classes/DataContainer.html +234 -0
  107. data/doc/rdoc/classes/DataContainer.src/M000101.html +26 -0
  108. data/doc/rdoc/classes/DataContainer.src/M000102.html +24 -0
  109. data/doc/rdoc/classes/DataContainer.src/M000103.html +23 -0
  110. data/doc/rdoc/classes/DataContainer.src/M000104.html +26 -0
  111. data/doc/rdoc/classes/DataContainer.src/M000105.html +22 -0
  112. data/doc/rdoc/classes/DataContainer.src/M000106.html +18 -0
  113. data/doc/rdoc/classes/DataStorage.html +199 -0
  114. data/doc/rdoc/classes/DataStorage.src/M000031.html +23 -0
  115. data/doc/rdoc/classes/DataStorage.src/M000032.html +36 -0
  116. data/doc/rdoc/classes/DataStorage.src/M000033.html +25 -0
  117. data/doc/rdoc/classes/DataStorage.src/M000034.html +30 -0
  118. data/doc/rdoc/classes/DataStorage.src/M000035.html +21 -0
  119. data/doc/rdoc/classes/DefaultAction.html +187 -0
  120. data/doc/rdoc/classes/DefaultAction.src/M000014.html +23 -0
  121. data/doc/rdoc/classes/DefaultAction.src/M000015.html +36 -0
  122. data/doc/rdoc/classes/DefaultAction.src/M000016.html +38 -0
  123. data/doc/rdoc/classes/DefaultLoggerFactory.html +140 -0
  124. data/doc/rdoc/classes/DefaultLoggerFactory.src/M000169.html +19 -0
  125. data/doc/rdoc/classes/DirectLinkContainer.html +156 -0
  126. data/doc/rdoc/classes/DirectLinkContainer.src/M000209.html +19 -0
  127. data/doc/rdoc/classes/DirectLinkContainer.src/M000210.html +18 -0
  128. data/doc/rdoc/classes/DirectLinkParser.html +137 -0
  129. data/doc/rdoc/classes/DirectLinkParser.src/M000168.html +39 -0
  130. data/doc/rdoc/classes/DivTag.html +150 -0
  131. data/doc/rdoc/classes/DivTag.src/M000030.html +19 -0
  132. data/doc/rdoc/classes/EditAction.html +177 -0
  133. data/doc/rdoc/classes/EditAction.src/M000056.html +24 -0
  134. data/doc/rdoc/classes/EditAction.src/M000057.html +64 -0
  135. data/doc/rdoc/classes/EditActionAdapter.html +139 -0
  136. data/doc/rdoc/classes/EditActionAdapter.src/M000002.html +20 -0
  137. data/doc/rdoc/classes/EditCategoryAction.html +176 -0
  138. data/doc/rdoc/classes/EditCategoryAction.src/M000126.html +24 -0
  139. data/doc/rdoc/classes/EditCategoryAction.src/M000127.html +39 -0
  140. data/doc/rdoc/classes/EditCategoryActionAdapter.html +139 -0
  141. data/doc/rdoc/classes/EditCategoryActionAdapter.src/M000021.html +20 -0
  142. data/doc/rdoc/classes/EditCategoryPage.html +242 -0
  143. data/doc/rdoc/classes/EditCategoryPage.src/M000036.html +29 -0
  144. data/doc/rdoc/classes/EditCategoryPage.src/M000037.html +18 -0
  145. data/doc/rdoc/classes/EditCategoryPage.src/M000038.html +18 -0
  146. data/doc/rdoc/classes/EditCategoryPage.src/M000039.html +18 -0
  147. data/doc/rdoc/classes/EditCategoryPage.src/M000040.html +109 -0
  148. data/doc/rdoc/classes/EditCategoryPage.src/M000041.html +60 -0
  149. data/doc/rdoc/classes/EditCategoryPage.src/M000042.html +29 -0
  150. data/doc/rdoc/classes/EditNewActionAdapter.html +156 -0
  151. data/doc/rdoc/classes/EditNewActionAdapter.src/M000220.html +20 -0
  152. data/doc/rdoc/classes/EditNewActionAdapter.src/M000221.html +23 -0
  153. data/doc/rdoc/classes/EditPage.html +212 -0
  154. data/doc/rdoc/classes/EditPage.src/M000064.html +33 -0
  155. data/doc/rdoc/classes/EditPage.src/M000065.html +18 -0
  156. data/doc/rdoc/classes/EditPage.src/M000066.html +18 -0
  157. data/doc/rdoc/classes/EditPage.src/M000067.html +18 -0
  158. data/doc/rdoc/classes/EditPage.src/M000068.html +112 -0
  159. data/doc/rdoc/classes/EmphasisContainer.html +156 -0
  160. data/doc/rdoc/classes/EmphasisContainer.src/M000003.html +20 -0
  161. data/doc/rdoc/classes/EmphasisContainer.src/M000004.html +19 -0
  162. data/doc/rdoc/classes/EmphasisParser.html +176 -0
  163. data/doc/rdoc/classes/EmphasisParser.src/M000076.html +19 -0
  164. data/doc/rdoc/classes/EmphasisParser.src/M000077.html +18 -0
  165. data/doc/rdoc/classes/EmphasisParser.src/M000078.html +45 -0
  166. data/doc/rdoc/classes/EscapeParser.html +137 -0
  167. data/doc/rdoc/classes/EscapeParser.src/M000150.html +26 -0
  168. data/doc/rdoc/classes/ExpireMetaTag.html +139 -0
  169. data/doc/rdoc/classes/ExpireMetaTag.src/M000241.html +18 -0
  170. data/doc/rdoc/classes/FilePersistentStorageHandler.html +207 -0
  171. data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000215.html +27 -0
  172. data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000216.html +21 -0
  173. data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000217.html +19 -0
  174. data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000218.html +19 -0
  175. data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000219.html +20 -0
  176. data/doc/rdoc/classes/FormAction.html +169 -0
  177. data/doc/rdoc/classes/FormAction.src/M000081.html +18 -0
  178. data/doc/rdoc/classes/FormAction.src/M000082.html +30 -0
  179. data/doc/rdoc/classes/FormActionAdapter.html +171 -0
  180. data/doc/rdoc/classes/FormActionAdapter.src/M000086.html +19 -0
  181. data/doc/rdoc/classes/FormActionAdapter.src/M000087.html +18 -0
  182. data/doc/rdoc/classes/FormActionAdapter.src/M000088.html +18 -0
  183. data/doc/rdoc/classes/FormActionElement.html +169 -0
  184. data/doc/rdoc/classes/FormActionElement.src/M000044.html +18 -0
  185. data/doc/rdoc/classes/FormActionElement.src/M000045.html +18 -0
  186. data/doc/rdoc/classes/FormActionElement.src/M000046.html +23 -0
  187. data/doc/rdoc/classes/FormInputTag.html +165 -0
  188. data/doc/rdoc/classes/FormInputTag.src/M000161.html +21 -0
  189. data/doc/rdoc/classes/HiddenFormInputTag.html +139 -0
  190. data/doc/rdoc/classes/HiddenFormInputTag.src/M000027.html +18 -0
  191. data/doc/rdoc/classes/IDataStorage.html +170 -0
  192. data/doc/rdoc/classes/IDataStorage.src/M000382.html +18 -0
  193. data/doc/rdoc/classes/IDataStorage.src/M000383.html +18 -0
  194. data/doc/rdoc/classes/IDataStorage.src/M000384.html +18 -0
  195. data/doc/rdoc/classes/ItalicContainer.html +139 -0
  196. data/doc/rdoc/classes/ItalicContainer.src/M000128.html +18 -0
  197. data/doc/rdoc/classes/ItalicParser.html +156 -0
  198. data/doc/rdoc/classes/ItalicParser.src/M000207.html +18 -0
  199. data/doc/rdoc/classes/ItalicParser.src/M000208.html +18 -0
  200. data/doc/rdoc/classes/LinkActionElement.html +184 -0
  201. data/doc/rdoc/classes/LinkActionElement.src/M000005.html +18 -0
  202. data/doc/rdoc/classes/LinkActionElement.src/M000006.html +18 -0
  203. data/doc/rdoc/classes/LinkActionElement.src/M000007.html +18 -0
  204. data/doc/rdoc/classes/LinkActionElement.src/M000008.html +18 -0
  205. data/doc/rdoc/classes/LinkTag.html +187 -0
  206. data/doc/rdoc/classes/LinkTag.src/M000153.html +34 -0
  207. data/doc/rdoc/classes/LinkTag.src/M000154.html +18 -0
  208. data/doc/rdoc/classes/LinkTag.src/M000155.html +20 -0
  209. data/doc/rdoc/classes/ListContainer.html +156 -0
  210. data/doc/rdoc/classes/ListContainer.src/M000174.html +18 -0
  211. data/doc/rdoc/classes/ListContainer.src/M000175.html +19 -0
  212. data/doc/rdoc/classes/ListItemContainer.html +156 -0
  213. data/doc/rdoc/classes/ListItemContainer.src/M000028.html +19 -0
  214. data/doc/rdoc/classes/ListItemContainer.src/M000029.html +19 -0
  215. data/doc/rdoc/classes/ListParser.html +144 -0
  216. data/doc/rdoc/classes/ListParser.src/M000195.html +147 -0
  217. data/doc/rdoc/classes/ListParserUtils.html +141 -0
  218. data/doc/rdoc/classes/ListParserUtils.src/M000385.html +23 -0
  219. data/doc/rdoc/classes/Localization.html +209 -0
  220. data/doc/rdoc/classes/Localization.src/M000311.html +40 -0
  221. data/doc/rdoc/classes/Localization.src/M000312.html +23 -0
  222. data/doc/rdoc/classes/Log4r.html +111 -0
  223. data/doc/rdoc/classes/Log4r/ExtendedRollingFileOutputter.html +178 -0
  224. data/doc/rdoc/classes/Log4r/ExtendedRollingFileOutputter.src/M000380.html +25 -0
  225. data/doc/rdoc/classes/Log4r/ExtendedRollingFileOutputter.src/M000381.html +33 -0
  226. data/doc/rdoc/classes/LoggerFactory.html +152 -0
  227. data/doc/rdoc/classes/LoggerFactory.src/M000062.html +22 -0
  228. data/doc/rdoc/classes/LoggerFactory.src/M000063.html +18 -0
  229. data/doc/rdoc/classes/MetaTag.html +166 -0
  230. data/doc/rdoc/classes/MetaTag.src/M000118.html +20 -0
  231. data/doc/rdoc/classes/NoCacheMetaTag.html +139 -0
  232. data/doc/rdoc/classes/NoCacheMetaTag.src/M000043.html +18 -0
  233. data/doc/rdoc/classes/PageRequest.html +259 -0
  234. data/doc/rdoc/classes/PageRequest.src/M000179.html +20 -0
  235. data/doc/rdoc/classes/PageRequest.src/M000180.html +18 -0
  236. data/doc/rdoc/classes/PageRequest.src/M000181.html +18 -0
  237. data/doc/rdoc/classes/PageRequest.src/M000182.html +18 -0
  238. data/doc/rdoc/classes/PageRequest.src/M000183.html +19 -0
  239. data/doc/rdoc/classes/PageRequest.src/M000184.html +23 -0
  240. data/doc/rdoc/classes/PageRequest.src/M000185.html +23 -0
  241. data/doc/rdoc/classes/PageRequest.src/M000186.html +19 -0
  242. data/doc/rdoc/classes/PageRequest.src/M000187.html +18 -0
  243. data/doc/rdoc/classes/PageResponse.html +250 -0
  244. data/doc/rdoc/classes/PageResponse.src/M000092.html +18 -0
  245. data/doc/rdoc/classes/PageResponse.src/M000093.html +18 -0
  246. data/doc/rdoc/classes/PageResponse.src/M000094.html +18 -0
  247. data/doc/rdoc/classes/PageResponse.src/M000095.html +18 -0
  248. data/doc/rdoc/classes/PageResponse.src/M000096.html +18 -0
  249. data/doc/rdoc/classes/PageResponse.src/M000097.html +18 -0
  250. data/doc/rdoc/classes/PageResponse.src/M000098.html +18 -0
  251. data/doc/rdoc/classes/PageResponse.src/M000099.html +18 -0
  252. data/doc/rdoc/classes/ParagraphContainer.html +156 -0
  253. data/doc/rdoc/classes/ParagraphContainer.src/M000158.html +19 -0
  254. data/doc/rdoc/classes/ParagraphContainer.src/M000159.html +24 -0
  255. data/doc/rdoc/classes/ParagraphParser.html +137 -0
  256. data/doc/rdoc/classes/ParagraphParser.src/M000151.html +42 -0
  257. data/doc/rdoc/classes/PersistentStorageHandler.html +182 -0
  258. data/doc/rdoc/classes/PersistentStorageHandler.src/M000376.html +18 -0
  259. data/doc/rdoc/classes/PersistentStorageHandler.src/M000377.html +18 -0
  260. data/doc/rdoc/classes/PersistentStorageHandler.src/M000378.html +18 -0
  261. data/doc/rdoc/classes/PersistentStorageHandler.src/M000379.html +18 -0
  262. data/doc/rdoc/classes/Pid.html +182 -0
  263. data/doc/rdoc/classes/Pid.src/M000083.html +18 -0
  264. data/doc/rdoc/classes/Pid.src/M000084.html +24 -0
  265. data/doc/rdoc/classes/Pid.src/M000085.html +18 -0
  266. data/doc/rdoc/classes/Properties.html +184 -0
  267. data/doc/rdoc/classes/Properties.src/M000058.html +18 -0
  268. data/doc/rdoc/classes/Properties.src/M000059.html +18 -0
  269. data/doc/rdoc/classes/Properties.src/M000060.html +18 -0
  270. data/doc/rdoc/classes/Properties.src/M000061.html +27 -0
  271. data/doc/rdoc/classes/PropertyList.html +187 -0
  272. data/doc/rdoc/classes/PropertyList.src/M000017.html +19 -0
  273. data/doc/rdoc/classes/PropertyList.src/M000018.html +23 -0
  274. data/doc/rdoc/classes/PropertyList.src/M000019.html +23 -0
  275. data/doc/rdoc/classes/PropertyList.src/M000020.html +18 -0
  276. data/doc/rdoc/classes/RawAttribute.html +154 -0
  277. data/doc/rdoc/classes/RawAttribute.src/M000249.html +20 -0
  278. data/doc/rdoc/classes/RawAttribute.src/M000250.html +21 -0
  279. data/doc/rdoc/classes/RawPage.html +171 -0
  280. data/doc/rdoc/classes/RawPage.src/M000107.html +19 -0
  281. data/doc/rdoc/classes/RawPage.src/M000108.html +18 -0
  282. data/doc/rdoc/classes/RawPage.src/M000109.html +18 -0
  283. data/doc/rdoc/classes/ReferenceLinkContainer.html +156 -0
  284. data/doc/rdoc/classes/ReferenceLinkContainer.src/M000213.html +20 -0
  285. data/doc/rdoc/classes/ReferenceLinkContainer.src/M000214.html +19 -0
  286. data/doc/rdoc/classes/Ribit.html +124 -0
  287. data/doc/rdoc/classes/Ribit/ContentStore.html +236 -0
  288. data/doc/rdoc/classes/Ribit/ContentStore.src/M000304.html +23 -0
  289. data/doc/rdoc/classes/Ribit/ContentStore.src/M000305.html +29 -0
  290. data/doc/rdoc/classes/Ribit/ContentStore.src/M000306.html +25 -0
  291. data/doc/rdoc/classes/Ribit/ContentStore.src/M000307.html +49 -0
  292. data/doc/rdoc/classes/Ribit/ContentStore.src/M000308.html +18 -0
  293. data/doc/rdoc/classes/Ribit/ContentStore.src/M000309.html +73 -0
  294. data/doc/rdoc/classes/Ribit/ContentStore.src/M000310.html +51 -0
  295. data/doc/rdoc/classes/Ribit/FileWriter.html +162 -0
  296. data/doc/rdoc/classes/Ribit/FileWriter.src/M000289.html +19 -0
  297. data/doc/rdoc/classes/Ribit/FileWriter.src/M000290.html +32 -0
  298. data/doc/rdoc/classes/Ribit/Repository.html +174 -0
  299. data/doc/rdoc/classes/Ribit/Repository.src/M000276.html +18 -0
  300. data/doc/rdoc/classes/Ribit/Repository.src/M000277.html +18 -0
  301. data/doc/rdoc/classes/Ribit/Repository.src/M000278.html +18 -0
  302. data/doc/rdoc/classes/Ribit/RibitLogger.html +137 -0
  303. data/doc/rdoc/classes/Ribit/RibitLogger.src/M000301.html +18 -0
  304. data/doc/rdoc/classes/Ribit/RibitLoggerConfig.html +182 -0
  305. data/doc/rdoc/classes/Ribit/RibitLoggerConfig.src/M000279.html +18 -0
  306. data/doc/rdoc/classes/Ribit/RibitLoggerConfig.src/M000280.html +23 -0
  307. data/doc/rdoc/classes/Ribit/RibitLoggerConfig.src/M000281.html +21 -0
  308. data/doc/rdoc/classes/Ribit/RibitLoggerConfig.src/M000282.html +18 -0
  309. data/doc/rdoc/classes/Ribit/RibitLoggerFactory.html +154 -0
  310. data/doc/rdoc/classes/Ribit/RibitLoggerFactory.src/M000287.html +18 -0
  311. data/doc/rdoc/classes/Ribit/RibitLoggerFactory.src/M000288.html +25 -0
  312. data/doc/rdoc/classes/Ribit/RibitLoggerImpl.html +229 -0
  313. data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000294.html +26 -0
  314. data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000295.html +18 -0
  315. data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000296.html +18 -0
  316. data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000297.html +18 -0
  317. data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000298.html +18 -0
  318. data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000299.html +18 -0
  319. data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000300.html +18 -0
  320. data/doc/rdoc/classes/Ribit/RibitLoggerWrapper.html +210 -0
  321. data/doc/rdoc/classes/Ribit/RibitLoggerWrapper.src/M000291.html +20 -0
  322. data/doc/rdoc/classes/Ribit/RibitLoggerWrapper.src/M000292.html +32 -0
  323. data/doc/rdoc/classes/Ribit/RibitLoggerWrapper.src/M000293.html +18 -0
  324. data/doc/rdoc/classes/Ribit/Writer.html +163 -0
  325. data/doc/rdoc/classes/Ribit/Writer.src/M000302.html +18 -0
  326. data/doc/rdoc/classes/Ribit/Writer.src/M000303.html +21 -0
  327. data/doc/rdoc/classes/RibitConfig.html +247 -0
  328. data/doc/rdoc/classes/RibitConfig.src/M000072.html +32 -0
  329. data/doc/rdoc/classes/RibitConfig.src/M000073.html +18 -0
  330. data/doc/rdoc/classes/RibitConfig.src/M000074.html +18 -0
  331. data/doc/rdoc/classes/RibitConfig.src/M000075.html +18 -0
  332. data/doc/rdoc/classes/RibitConfigParser.html +140 -0
  333. data/doc/rdoc/classes/RibitConfigParser.src/M000117.html +45 -0
  334. data/doc/rdoc/classes/RibitData.html +128 -0
  335. data/doc/rdoc/classes/RibitData/CategoriesWriter.html +169 -0
  336. data/doc/rdoc/classes/RibitData/CategoriesWriter.src/M000338.html +18 -0
  337. data/doc/rdoc/classes/RibitData/CategoriesWriter.src/M000339.html +27 -0
  338. data/doc/rdoc/classes/RibitData/CategoriesWriter.src/M000340.html +24 -0
  339. data/doc/rdoc/classes/RibitData/Category.html +485 -0
  340. data/doc/rdoc/classes/RibitData/Category.src/M000313.html +27 -0
  341. data/doc/rdoc/classes/RibitData/Category.src/M000314.html +36 -0
  342. data/doc/rdoc/classes/RibitData/Category.src/M000315.html +22 -0
  343. data/doc/rdoc/classes/RibitData/Category.src/M000316.html +18 -0
  344. data/doc/rdoc/classes/RibitData/Category.src/M000317.html +18 -0
  345. data/doc/rdoc/classes/RibitData/Category.src/M000318.html +18 -0
  346. data/doc/rdoc/classes/RibitData/Category.src/M000319.html +18 -0
  347. data/doc/rdoc/classes/RibitData/Category.src/M000320.html +18 -0
  348. data/doc/rdoc/classes/RibitData/Category.src/M000321.html +18 -0
  349. data/doc/rdoc/classes/RibitData/Category.src/M000322.html +18 -0
  350. data/doc/rdoc/classes/RibitData/Category.src/M000323.html +18 -0
  351. data/doc/rdoc/classes/RibitData/Category.src/M000324.html +18 -0
  352. data/doc/rdoc/classes/RibitData/Category.src/M000325.html +18 -0
  353. data/doc/rdoc/classes/RibitData/Category.src/M000326.html +18 -0
  354. data/doc/rdoc/classes/RibitData/Category.src/M000327.html +36 -0
  355. data/doc/rdoc/classes/RibitData/Category.src/M000328.html +18 -0
  356. data/doc/rdoc/classes/RibitData/Category.src/M000329.html +48 -0
  357. data/doc/rdoc/classes/RibitData/Category.src/M000330.html +45 -0
  358. data/doc/rdoc/classes/RibitData/Category.src/M000331.html +30 -0
  359. data/doc/rdoc/classes/RibitData/Category.src/M000332.html +25 -0
  360. data/doc/rdoc/classes/RibitData/Category.src/M000333.html +18 -0
  361. data/doc/rdoc/classes/RibitData/CategoryParser.html +217 -0
  362. data/doc/rdoc/classes/RibitData/CategoryParser.src/M000357.html +18 -0
  363. data/doc/rdoc/classes/RibitData/CategoryParser.src/M000358.html +29 -0
  364. data/doc/rdoc/classes/RibitData/CategoryParser.src/M000359.html +31 -0
  365. data/doc/rdoc/classes/RibitData/CategoryParser.src/M000360.html +27 -0
  366. data/doc/rdoc/classes/RibitData/CategoryParser.src/M000361.html +45 -0
  367. data/doc/rdoc/classes/RibitData/Page.html +313 -0
  368. data/doc/rdoc/classes/RibitData/Page.src/M000362.html +33 -0
  369. data/doc/rdoc/classes/RibitData/Page.src/M000363.html +22 -0
  370. data/doc/rdoc/classes/RibitData/Page.src/M000364.html +18 -0
  371. data/doc/rdoc/classes/RibitData/Page.src/M000365.html +18 -0
  372. data/doc/rdoc/classes/RibitData/Page.src/M000366.html +18 -0
  373. data/doc/rdoc/classes/RibitData/Page.src/M000367.html +46 -0
  374. data/doc/rdoc/classes/RibitData/Page.src/M000368.html +26 -0
  375. data/doc/rdoc/classes/RibitData/PageParser.html +190 -0
  376. data/doc/rdoc/classes/RibitData/PageParser.src/M000334.html +19 -0
  377. data/doc/rdoc/classes/RibitData/PageParser.src/M000335.html +32 -0
  378. data/doc/rdoc/classes/RibitData/PageParser.src/M000336.html +42 -0
  379. data/doc/rdoc/classes/RibitData/PageParser.src/M000337.html +21 -0
  380. data/doc/rdoc/classes/RibitData/RibitData.html +389 -0
  381. data/doc/rdoc/classes/RibitData/RibitData.src/M000341.html +26 -0
  382. data/doc/rdoc/classes/RibitData/RibitData.src/M000342.html +22 -0
  383. data/doc/rdoc/classes/RibitData/RibitData.src/M000343.html +18 -0
  384. data/doc/rdoc/classes/RibitData/RibitData.src/M000344.html +36 -0
  385. data/doc/rdoc/classes/RibitData/RibitData.src/M000345.html +18 -0
  386. data/doc/rdoc/classes/RibitData/RibitData.src/M000346.html +25 -0
  387. data/doc/rdoc/classes/RibitData/RibitData.src/M000347.html +18 -0
  388. data/doc/rdoc/classes/RibitData/RibitData.src/M000348.html +22 -0
  389. data/doc/rdoc/classes/RibitData/RibitData.src/M000349.html +18 -0
  390. data/doc/rdoc/classes/RibitData/RibitData.src/M000350.html +30 -0
  391. data/doc/rdoc/classes/RibitData/RibitData.src/M000351.html +18 -0
  392. data/doc/rdoc/classes/RibitData/RibitData.src/M000352.html +48 -0
  393. data/doc/rdoc/classes/RibitData/RibitData.src/M000353.html +30 -0
  394. data/doc/rdoc/classes/RibitData/RibitData.src/M000354.html +22 -0
  395. data/doc/rdoc/classes/RibitData/RibitData.src/M000355.html +22 -0
  396. data/doc/rdoc/classes/RibitData/RibitData.src/M000356.html +22 -0
  397. data/doc/rdoc/classes/RibitData/RibitDataException.html +113 -0
  398. data/doc/rdoc/classes/RibitException.html +117 -0
  399. data/doc/rdoc/classes/RibitLinkContainer.html +156 -0
  400. data/doc/rdoc/classes/RibitLinkContainer.src/M000211.html +85 -0
  401. data/doc/rdoc/classes/RibitLinkContainer.src/M000212.html +18 -0
  402. data/doc/rdoc/classes/RibitLinkParser.html +137 -0
  403. data/doc/rdoc/classes/RibitLinkParser.src/M000100.html +50 -0
  404. data/doc/rdoc/classes/RibitServlet.html +196 -0
  405. data/doc/rdoc/classes/RibitServlet.src/M000222.html +37 -0
  406. data/doc/rdoc/classes/RibitServlet.src/M000223.html +53 -0
  407. data/doc/rdoc/classes/RibitServlet.src/M000224.html +39 -0
  408. data/doc/rdoc/classes/RibitServlet.src/M000225.html +19 -0
  409. data/doc/rdoc/classes/RootContainer.html +139 -0
  410. data/doc/rdoc/classes/RootContainer.src/M000206.html +19 -0
  411. data/doc/rdoc/classes/SaveAction.html +164 -0
  412. data/doc/rdoc/classes/SaveAction.src/M000162.html +24 -0
  413. data/doc/rdoc/classes/SaveAction.src/M000163.html +116 -0
  414. data/doc/rdoc/classes/SaveCategoryAction.html +164 -0
  415. data/doc/rdoc/classes/SaveCategoryAction.src/M000047.html +24 -0
  416. data/doc/rdoc/classes/SaveCategoryAction.src/M000048.html +97 -0
  417. data/doc/rdoc/classes/SectionContainer.html +156 -0
  418. data/doc/rdoc/classes/SectionContainer.src/M000070.html +19 -0
  419. data/doc/rdoc/classes/SectionContainer.src/M000071.html +20 -0
  420. data/doc/rdoc/classes/SectionParser.html +137 -0
  421. data/doc/rdoc/classes/SectionParser.src/M000152.html +41 -0
  422. data/doc/rdoc/classes/SelectOptionTag.html +177 -0
  423. data/doc/rdoc/classes/SelectOptionTag.src/M000156.html +22 -0
  424. data/doc/rdoc/classes/SelectOptionTag.src/M000157.html +18 -0
  425. data/doc/rdoc/classes/StyleSheetAction.html +182 -0
  426. data/doc/rdoc/classes/StyleSheetAction.src/M000226.html +31 -0
  427. data/doc/rdoc/classes/StyleSheetAction.src/M000227.html +36 -0
  428. data/doc/rdoc/classes/TextContainer.html +214 -0
  429. data/doc/rdoc/classes/TextContainer.src/M000050.html +19 -0
  430. data/doc/rdoc/classes/TextContainer.src/M000051.html +18 -0
  431. data/doc/rdoc/classes/TextContainer.src/M000052.html +18 -0
  432. data/doc/rdoc/classes/TextContainer.src/M000053.html +18 -0
  433. data/doc/rdoc/classes/TextContainer.src/M000054.html +18 -0
  434. data/doc/rdoc/classes/TextContainer.src/M000055.html +18 -0
  435. data/doc/rdoc/classes/TextPage.html +226 -0
  436. data/doc/rdoc/classes/TextPage.src/M000198.html +29 -0
  437. data/doc/rdoc/classes/TextPage.src/M000199.html +18 -0
  438. data/doc/rdoc/classes/TextPage.src/M000200.html +54 -0
  439. data/doc/rdoc/classes/TextPage.src/M000201.html +36 -0
  440. data/doc/rdoc/classes/TextPage.src/M000202.html +46 -0
  441. data/doc/rdoc/classes/TextPage.src/M000203.html +25 -0
  442. data/doc/rdoc/classes/URL.html +182 -0
  443. data/doc/rdoc/classes/URL.src/M000123.html +24 -0
  444. data/doc/rdoc/classes/URL.src/M000124.html +19 -0
  445. data/doc/rdoc/classes/URL.src/M000125.html +35 -0
  446. data/doc/rdoc/classes/UnformattedContentContainer.html +156 -0
  447. data/doc/rdoc/classes/UnformattedContentContainer.src/M000079.html +20 -0
  448. data/doc/rdoc/classes/UnformattedContentContainer.src/M000080.html +20 -0
  449. data/doc/rdoc/classes/UnformattedContentParser.html +137 -0
  450. data/doc/rdoc/classes/UnformattedContentParser.src/M000194.html +49 -0
  451. data/doc/rdoc/classes/ViewAction.html +221 -0
  452. data/doc/rdoc/classes/ViewAction.src/M000009.html +25 -0
  453. data/doc/rdoc/classes/ViewAction.src/M000010.html +20 -0
  454. data/doc/rdoc/classes/ViewAction.src/M000011.html +77 -0
  455. data/doc/rdoc/classes/ViewAction.src/M000012.html +18 -0
  456. data/doc/rdoc/classes/ViewAction.src/M000013.html +22 -0
  457. data/doc/rdoc/classes/ViewActionAdapter.html +186 -0
  458. data/doc/rdoc/classes/ViewActionAdapter.src/M000022.html +20 -0
  459. data/doc/rdoc/classes/ViewActionAdapter.src/M000023.html +24 -0
  460. data/doc/rdoc/classes/ViewActionAdapter.src/M000024.html +20 -0
  461. data/doc/rdoc/classes/ViewActionAdapter.src/M000025.html +21 -0
  462. data/doc/rdoc/classes/ViewCategoriesAction.html +211 -0
  463. data/doc/rdoc/classes/ViewCategoriesAction.src/M000261.html +25 -0
  464. data/doc/rdoc/classes/ViewCategoriesAction.src/M000262.html +20 -0
  465. data/doc/rdoc/classes/ViewCategoriesAction.src/M000263.html +61 -0
  466. data/doc/rdoc/classes/ViewCategoriesAction.src/M000264.html +22 -0
  467. data/doc/rdoc/classes/ViewCategoriesActionAdapter.html +171 -0
  468. data/doc/rdoc/classes/ViewCategoriesActionAdapter.src/M000089.html +18 -0
  469. data/doc/rdoc/classes/ViewCategoriesActionAdapter.src/M000090.html +24 -0
  470. data/doc/rdoc/classes/ViewCategoriesActionAdapter.src/M000091.html +18 -0
  471. data/doc/rdoc/classes/W3CValidatorLinkActionAdapter.html +156 -0
  472. data/doc/rdoc/classes/W3CValidatorLinkActionAdapter.src/M000110.html +26 -0
  473. data/doc/rdoc/classes/W3CValidatorLinkActionAdapter.src/M000111.html +18 -0
  474. data/doc/rdoc/classes/WebAction.html +165 -0
  475. data/doc/rdoc/classes/WebAction.src/M000242.html +18 -0
  476. data/doc/rdoc/classes/WebAction.src/M000243.html +19 -0
  477. data/doc/rdoc/classes/WebPage.html +184 -0
  478. data/doc/rdoc/classes/WebPage.src/M000170.html +17 -0
  479. data/doc/rdoc/classes/WebPage.src/M000171.html +19 -0
  480. data/doc/rdoc/classes/WebPage.src/M000172.html +18 -0
  481. data/doc/rdoc/classes/WebPage.src/M000173.html +18 -0
  482. data/doc/rdoc/classes/XHTMLDocument.html +377 -0
  483. data/doc/rdoc/classes/XHTMLDocument.src/M000136.html +26 -0
  484. data/doc/rdoc/classes/XHTMLDocument.src/M000137.html +40 -0
  485. data/doc/rdoc/classes/XHTMLDocument.src/M000138.html +20 -0
  486. data/doc/rdoc/classes/XHTMLDocument.src/M000139.html +18 -0
  487. data/doc/rdoc/classes/XHTMLDocument.src/M000140.html +18 -0
  488. data/doc/rdoc/classes/XHTMLDocument.src/M000141.html +19 -0
  489. data/doc/rdoc/classes/XHTMLDocument.src/M000142.html +21 -0
  490. data/doc/rdoc/classes/XHTMLDocument.src/M000143.html +30 -0
  491. data/doc/rdoc/classes/XHTMLDocument.src/M000144.html +18 -0
  492. data/doc/rdoc/classes/XHTMLDocument.src/M000145.html +18 -0
  493. data/doc/rdoc/classes/XHTMLDocument.src/M000146.html +23 -0
  494. data/doc/rdoc/classes/XHTMLDocument.src/M000147.html +18 -0
  495. data/doc/rdoc/classes/XHTMLException.html +117 -0
  496. data/doc/rdoc/classes/XHTMLPage.html +225 -0
  497. data/doc/rdoc/classes/XHTMLPage.src/M000188.html +20 -0
  498. data/doc/rdoc/classes/XHTMLPage.src/M000189.html +18 -0
  499. data/doc/rdoc/classes/XHTMLPage.src/M000190.html +44 -0
  500. data/doc/rdoc/classes/XHTMLPage.src/M000191.html +18 -0
  501. data/doc/rdoc/classes/XHTMLPage.src/M000192.html +54 -0
  502. data/doc/rdoc/classes/XHTMLPage.src/M000193.html +22 -0
  503. data/doc/rdoc/created.rid +1 -0
  504. data/doc/rdoc/files/CHANGES.html +150 -0
  505. data/doc/rdoc/files/INSTALL.html +169 -0
  506. data/doc/rdoc/files/LICENSE.html +449 -0
  507. data/doc/rdoc/files/README.html +176 -0
  508. data/doc/rdoc/files/lib/common/assert_rb.html +101 -0
  509. data/doc/rdoc/files/lib/common/cvs_rb.html +116 -0
  510. data/doc/rdoc/files/lib/common/datastorage_rb.html +108 -0
  511. data/doc/rdoc/files/lib/common/loggerfactory_rb.html +108 -0
  512. data/doc/rdoc/files/lib/common/pid_rb.html +101 -0
  513. data/doc/rdoc/files/lib/common/properties_rb.html +101 -0
  514. data/doc/rdoc/files/lib/common/url_rb.html +108 -0
  515. data/doc/rdoc/files/lib/log4r/outputter/extendedrollingfileoutputter_rb.html +111 -0
  516. data/doc/rdoc/files/lib/ribit/action_rb.html +116 -0
  517. data/doc/rdoc/files/lib/ribit/actionelement_rb.html +108 -0
  518. data/doc/rdoc/files/lib/ribit/common_rb.html +130 -0
  519. data/doc/rdoc/files/lib/ribit/common_rb.src/M000001.html +25 -0
  520. data/doc/rdoc/files/lib/ribit/config_rb.html +116 -0
  521. data/doc/rdoc/files/lib/ribit/constants_rb.html +101 -0
  522. data/doc/rdoc/files/lib/ribit/contentparser_rb.html +112 -0
  523. data/doc/rdoc/files/lib/ribit/contentstore_rb.html +112 -0
  524. data/doc/rdoc/files/lib/ribit/localization_rb.html +108 -0
  525. data/doc/rdoc/files/lib/ribit/main_rb.html +120 -0
  526. data/doc/rdoc/files/lib/ribit/ribit_rb.html +123 -0
  527. data/doc/rdoc/files/lib/ribit/ribitdata_rb.html +112 -0
  528. data/doc/rdoc/files/lib/ribit/ribitlogger_rb.html +111 -0
  529. data/doc/rdoc/files/lib/ribit/webpage_rb.html +118 -0
  530. data/doc/rdoc/files/lib/ribit/xhtmldocument_rb.html +109 -0
  531. data/doc/rdoc/files/lib/ribit/xhtmltag_rb.html +109 -0
  532. data/doc/rdoc/fr_class_index.html +150 -0
  533. data/doc/rdoc/fr_file_index.html +53 -0
  534. data/doc/rdoc/fr_method_index.html +411 -0
  535. data/doc/rdoc/index.html +24 -0
  536. data/doc/rdoc/rdoc-style.css +208 -0
  537. data/doc/spec.txt +42 -0
  538. data/doc/test_run_25052005.txt +108 -0
  539. data/doc/testplan.txt +87 -0
  540. data/doc/www/index.html +5 -0
  541. data/lib/common/assert.rb +72 -0
  542. data/lib/common/cvs.rb +201 -0
  543. data/lib/common/datastorage.rb +265 -0
  544. data/lib/common/loggerfactory.rb +56 -0
  545. data/lib/common/pid.rb +44 -0
  546. data/lib/common/properties.rb +89 -0
  547. data/lib/common/url.rb +64 -0
  548. data/lib/log4r/outputter/extendedrollingfileoutputter.rb +73 -0
  549. data/lib/ribit/action.rb +1106 -0
  550. data/lib/ribit/actionelement.rb +152 -0
  551. data/lib/ribit/common.rb +34 -0
  552. data/lib/ribit/config.rb +123 -0
  553. data/lib/ribit/constants.rb +50 -0
  554. data/lib/ribit/contentparser.rb +1111 -0
  555. data/lib/ribit/contentstore.rb +406 -0
  556. data/lib/ribit/localization.rb +76 -0
  557. data/lib/ribit/main.rb +114 -0
  558. data/lib/ribit/ribit.rb +319 -0
  559. data/lib/ribit/ribitdata.rb +909 -0
  560. data/lib/ribit/ribitlogger.rb +192 -0
  561. data/lib/ribit/webpage.rb +802 -0
  562. data/lib/ribit/xhtmldocument.rb +148 -0
  563. data/lib/ribit/xhtmltag.rb +189 -0
  564. data/share/config/content/1/1.xml +6 -0
  565. data/share/config/content/1/2.xml +6 -0
  566. data/share/config/content/1/3.xml +6 -0
  567. data/share/config/content/1/4.xml +6 -0
  568. data/share/config/content/1/5.xml +6 -0
  569. data/share/config/content/1/category.xml +7 -0
  570. data/share/config/content/1/files/edit-category-template.html +59 -0
  571. data/share/config/content/1/files/edit-template.html +88 -0
  572. data/share/config/content/1/files/localization_en.properties +11 -0
  573. data/share/config/content/1/files/ribit.css +215 -0
  574. data/share/config/content/1/files/view-template.html +50 -0
  575. data/share/config/content/2/1.xml +19 -0
  576. data/share/config/content/2/2.xml +54 -0
  577. data/share/config/content/2/category.xml +5 -0
  578. data/share/config/content/3/1.xml +11 -0
  579. data/share/config/content/3/3.xml +17 -0
  580. data/share/config/content/3/4.xml +28 -0
  581. data/share/config/content/3/category.xml +5 -0
  582. data/share/config/content/categories.xml +12 -0
  583. data/share/config/ribitconfig.xml +48 -0
  584. data/share/config/ribitconfig_dev.xml +41 -0
  585. data/share/config/ribitconfig_local.xml +39 -0
  586. data/share/test/config/content/1/1.xml +6 -0
  587. data/share/test/config/content/1/2.xml +6 -0
  588. data/share/test/config/content/1/3.xml +6 -0
  589. data/share/test/config/content/1/4.xml +6 -0
  590. data/share/test/config/content/1/category.xml +4 -0
  591. data/share/test/config/content/1/files/edit-template.html +50 -0
  592. data/share/test/config/content/1/files/localization_en.properties +4 -0
  593. data/share/test/config/content/1/files/ribit.css +139 -0
  594. data/share/test/config/content/1/files/view-template.html +36 -0
  595. data/share/test/config/content/2/1.xml +16 -0
  596. data/share/test/config/content/2/2.xml +25 -0
  597. data/share/test/config/content/2/category.xml +4 -0
  598. data/share/test/config/content/categories.xml +11 -0
  599. data/share/test/config/content/ribitdata.xml +348 -0
  600. data/share/test/config/ribitconfig.xml +36 -0
  601. data/share/test/test1.xml +13 -0
  602. data/share/test/test2.xml +17 -0
  603. data/share/test/test3.xml +5 -0
  604. data/test/alltests.rb +35 -0
  605. data/test/common/allcommontests.rb +40 -0
  606. data/test/common/asserttest.rb +71 -0
  607. data/test/common/cvstest.rb +117 -0
  608. data/test/common/datastoragetest.rb +151 -0
  609. data/test/common/filepersistentstoragehandlertest.rb +105 -0
  610. data/test/common/propertiestest.rb +77 -0
  611. data/test/common/urltest.rb +70 -0
  612. data/test/log4r/outputter/alllog4routputtertests.rb +28 -0
  613. data/test/log4r/outputter/extendedrollingfileoutputtertest.rb +77 -0
  614. data/test/mock/mock.rb +147 -0
  615. data/test/ribit/actionadaptertest.rb +58 -0
  616. data/test/ribit/actionelementtest.rb +147 -0
  617. data/test/ribit/actionmanagertest.rb +55 -0
  618. data/test/ribit/allribittests.rb +62 -0
  619. data/test/ribit/categoryformactiontest.rb +153 -0
  620. data/test/ribit/configtest.rb +43 -0
  621. data/test/ribit/contentparsertest.rb +404 -0
  622. data/test/ribit/contentstorestub.rb +64 -0
  623. data/test/ribit/contentstoretest.rb +222 -0
  624. data/test/ribit/editcategorypagetest.rb +121 -0
  625. data/test/ribit/formactiontest.rb +367 -0
  626. data/test/ribit/localizationtest.rb +65 -0
  627. data/test/ribit/loggertest.rb +44 -0
  628. data/test/ribit/misc/allmisctests.rb +32 -0
  629. data/test/ribit/misc/amritatest.rb +24 -0
  630. data/test/ribit/misc/debugservlet.rb +63 -0
  631. data/test/ribit/misc/postsevlet.rb +36 -0
  632. data/test/ribit/misc/rexmlcdatatest.rb +17 -0
  633. data/test/ribit/misc/rexmldoctypetest.rb +20 -0
  634. data/test/ribit/misc/rexmlreadtest.rb +13 -0
  635. data/test/ribit/misc/rexmlwritetest.rb +28 -0
  636. data/test/ribit/misc/rubytest.rb +184 -0
  637. data/test/ribit/misc/suidtest.rb +21 -0
  638. data/test/ribit/misc/suite.rb +12 -0
  639. data/test/ribit/misc/wwwtest.rb +68 -0
  640. data/test/ribit/pagerequesttest.rb +74 -0
  641. data/test/ribit/ribitdatatest.rb +404 -0
  642. data/test/ribit/ribitservlettest.rb +94 -0
  643. data/test/ribit/testdata/ribittestdata.rb +49 -0
  644. data/test/ribit/testutil/ribitstub.rb +83 -0
  645. data/test/ribit/testutil/ribittestcase.rb +66 -0
  646. data/test/ribit/viewactiontest.rb +332 -0
  647. data/test/ribit/webpagetest.rb +531 -0
  648. data/test/ribit/xhtmldocumenttest.rb +263 -0
  649. data/test/ribit/xhtmltagtest.rb +84 -0
  650. metadata +837 -0
@@ -0,0 +1,114 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ #--
4
+ # Copyright (C) 2004-2005 Tero Vuorela
5
+ #
6
+ # This program is free software; you can redistribute it and/or modify it
7
+ # under the terms of the GNU General Public License as published by the Free
8
+ # Software Foundation; either version 2 of the License, or (at your option)
9
+ # any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14
+ # more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along with
17
+ # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18
+ # Place - Suite 330, Boston, MA 02111-1307, USA.
19
+ #++
20
+
21
+ require 'webrick'
22
+ require 'ribit/ribit'
23
+ require 'ribit/config'
24
+ require 'ribit/contentstore'
25
+ require 'ribit/ribitlogger'
26
+ require 'common/pid'
27
+
28
+ include WEBrick
29
+
30
+ # default value for config file
31
+ configFileName = '/opt/ribit/ribitconfig.xml'
32
+
33
+ if ( ARGV[0] != nil )
34
+ configFileName = ARGV[0]
35
+ end
36
+
37
+ configParser = RibitConfigParser.new
38
+ ribitConfig = configParser.parse( configFileName )
39
+
40
+ # kickup HTTP server
41
+ port = ribitConfig[RibitConfig::HTTP_PORT].to_i
42
+ host = ribitConfig[RibitConfig::HTTP_HOST]
43
+ mountPoint = ribitConfig[RibitConfig::MOUNT_POINT]
44
+
45
+ logger = RibitLogger.new( 'main' )
46
+ accesslog = RibitLoggerWrapper.new( logger, RibitLoggerWrapper::INFO, 'accesslog: ' )
47
+ referer = RibitLoggerWrapper.new( logger, RibitLoggerWrapper::INFO, 'referer: ' )
48
+ agent = RibitLoggerWrapper.new( logger, RibitLoggerWrapper::INFO, 'agent: ' )
49
+ customlog = RibitLoggerWrapper.new( logger, RibitLoggerWrapper::INFO, 'customlog: ' )
50
+
51
+ logger.info( "Starting Ribit servlet to #{host}:#{port}#{mountPoint}" )
52
+
53
+ # :BindAddress forces to use IPv4 instead of IPv6, I think.
54
+ # Anyway with :BindAddress Webrick doesn't output:
55
+ # TCPServer Error: Address family not supported by protocol - socket(2)
56
+ server = HTTPServer.new(
57
+ :Port => port,
58
+ :Logger => logger,
59
+ :BindAddress => "0.0.0.0",
60
+ :AccessLog => [
61
+ [ accesslog, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
62
+ [ referer, WEBrick::AccessLog::REFERER_LOG_FORMAT ],
63
+ [ agent, WEBrick::AccessLog::AGENT_LOG_FORMAT ],
64
+ [ customlog, "%a %U %T" ] # peeraddr, Request-URI, process time
65
+ ] )
66
+
67
+ # ContentStore handles filesystem
68
+ store = Ribit::ContentStore.new( ribitConfig, Ribit::CVSRepository.new )
69
+
70
+ logger.info( "Loading Ribit page data..." )
71
+ ribitData = store.get_ribit_data
72
+ logger.info( "Ribit page data loaded" )
73
+
74
+ # RibitConfig is passed to servlet
75
+ server.mount( mountPoint, RibitServlet, ribitConfig, store, ribitData )
76
+ trap("INT") { server.shutdown }
77
+
78
+ # write the current pid to the file if a file is defined
79
+ pid = Pid.new
80
+ logger.info( 'The current pid is ' + pid.to_s )
81
+ pidFile = ribitConfig[RibitConfig::PID_FILE]
82
+
83
+ if ( pidFile != nil )
84
+ logger.info( 'Writing the current pid to ' + pidFile )
85
+ pid.write_to_file( pidFile )
86
+ end
87
+
88
+ # now everything is up and running we can change the used uid and gid
89
+ # (if needed). Works for Linux/Unix only.
90
+
91
+ uid = ribitConfig[RibitConfig::USER_ID]
92
+ gid = ribitConfig[RibitConfig::GROUP_ID]
93
+
94
+ # NOTE: we have set group first because after setting uid
95
+ # we lose rights to change gid
96
+
97
+ if ( gid != nil )
98
+ Process::egid = gid.to_i
99
+ Process::gid = gid.to_i
100
+ end
101
+
102
+ if ( uid != nil )
103
+ Process::euid = uid.to_i
104
+ Process::uid = uid.to_i
105
+ end
106
+
107
+ logger.info( "Using uid=#{Process::euid.to_s}, euid=#{Process::uid.to_s}" )
108
+ logger.info( "Using gid=#{Process::egid.to_s}, egid=#{Process::gid.to_s}" )
109
+
110
+ # start() call will never return
111
+ server.start
112
+
113
+
114
+
@@ -0,0 +1,319 @@
1
+ #--
2
+ # Copyright (C) 2004-2005 Tero Vuorela
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify it
5
+ # under the terms of the GNU General Public License as published by the Free
6
+ # Software Foundation; either version 2 of the License, or (at your option)
7
+ # any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
+ # more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License along with
15
+ # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16
+ # Place - Suite 330, Boston, MA 02111-1307, USA.
17
+ #++
18
+
19
+ require 'uri'
20
+ require 'webrick'
21
+ require 'ribit/ribitdata'
22
+ require 'ribit/action'
23
+ require 'ribit/config'
24
+ require 'ribit/common'
25
+ require 'ribit/constants'
26
+ require 'common/assert'
27
+ require 'common/datastorage'
28
+
29
+ include WEBrick
30
+
31
+ ##
32
+ #
33
+ class RibitServlet < HTTPServlet::AbstractServlet
34
+ include Assert
35
+
36
+ # The singleton instance of this servlet
37
+ @@instance = nil
38
+
39
+ # Return the one and only instanceof RibitServlet. WEBrick calls
40
+ # this method every time when request is made.
41
+ def self.get_instance( config, *options )
42
+
43
+ # 'config' is instance of WEBrick::HTTPServer, stored to @server
44
+ # config[:Logger] contains ref to WEBrick::Log, stored to @logger
45
+ # 'options' is Array
46
+ if ( @@instance == nil )
47
+ logger = config[:Logger]
48
+ logger.info( 'Creating a new servlet instance' )
49
+
50
+ begin
51
+ @@instance = self.new(config, options)
52
+ rescue Exception => error
53
+ logger.fatal( "Got error during servlet creation. No Servlet created" )
54
+ logger.fatal( format_exception( error ) )
55
+
56
+ # throw upwards, don't know what to do
57
+ raise error
58
+ end
59
+ end
60
+
61
+ return @@instance
62
+ end
63
+
64
+ #
65
+ def initialize( server, options )
66
+ super( server, options )
67
+
68
+ # RibitConfig and ContentStore are required,
69
+ # we can't proceed if it is missing
70
+
71
+ if ( @options[0] == nil )
72
+ raise RibitException, "No RibitConfig (1) found from servlet options", caller
73
+ end
74
+ @ribitConfig = options[0]
75
+
76
+ if ( options[1] == nil )
77
+ raise RibitException, "No ContentStore (2) found from servlet options", caller
78
+ end
79
+ @contentStore = options[1]
80
+ @ribitData = options[2]
81
+
82
+ # TODO: servlet should be changed that all actions are initialized only once => reload is not currently realible with caching
83
+ if ( @ribitConfig[RibitConfig::PAGE_CACHE_DIR] != nil )
84
+ dir = @ribitConfig[RibitConfig::PAGE_CACHE_DIR]
85
+ @logger.info( 'Cache path defined => page caching is enabled' )
86
+
87
+ # make sure dir exists
88
+ FileUtils.mkdir( dir ) unless File.exist?( dir )
89
+ storageHandler = FilePersistentStorageHandler.new( dir )
90
+
91
+ # TODO: pages in memory should be configurable
92
+ @pageCache = DataStorage.new( 10, -1, storageHandler )
93
+ else
94
+ # no cache path defined => no cache
95
+ @logger.info( 'No cache path defined => page caching is disabled' )
96
+ @pageCache = nil
97
+ end
98
+
99
+ # create all data structures
100
+ init
101
+
102
+ end
103
+
104
+ #
105
+ def do_GET(req, res)
106
+
107
+ begin
108
+ @logger.debug( "Processing GET" )
109
+
110
+ pageRequest = PageRequest.new( req )
111
+ pageResponse = PageResponse.new( res )
112
+
113
+ buildPage( pageRequest, pageResponse )
114
+
115
+ # used only for debugging
116
+ #@logger.debug( "Page=" + res.body )
117
+ rescue Exception => error
118
+ @logger.fatal( 'Got error during service request' )
119
+ @logger.fatal( format_exception( error ) )
120
+
121
+ # throw upwards, don't know what to do
122
+ raise error, error.message, error.backtrace
123
+ end
124
+
125
+ #@logger.debug( "content type = " + res['Content-Type'] )
126
+ #@logger.debug( "body = " + res.body )
127
+
128
+ end
129
+
130
+ #
131
+ def do_POST( req, res )
132
+ # forward call
133
+ return do_GET( req, res )
134
+ end
135
+
136
+ private
137
+
138
+ #
139
+ def buildPage( pageRequest, pageResponse )
140
+ @logger.debug( "Querying page by pageID #{pageRequest.get_requested_page_id}" )
141
+ action = @actionManager.get_action( pageRequest.get_action_id )
142
+ action.run( pageRequest, pageResponse )
143
+ end
144
+
145
+ #
146
+ def init
147
+ assert_not_nil( @ribitConfig )
148
+
149
+ if ( @ribitData == nil )
150
+ @ribitData = @contentStore.get_ribit_data
151
+ end
152
+ ribitData = @ribitData
153
+
154
+ @actionManager = ActionManager.new
155
+ @actionManager.register_action( ViewAction.new( ribitData, @ribitConfig, @pageCache ) )
156
+ @actionManager.register_action( StyleSheetAction.new( ribitData ) )
157
+ @actionManager.register_action( EditAction.new( ribitData, @ribitConfig ) )
158
+ @actionManager.register_action( ViewCategoriesAction.new( ribitData, @ribitConfig, @pageCache ) )
159
+ @actionManager.register_action( EditCategoryAction.new( ribitData, @ribitConfig ) )
160
+
161
+ formAction = FormAction.new( ribitData )
162
+
163
+ formAction.add_action( SaveAction.new(
164
+ ribitData,
165
+ @ribitConfig,
166
+ @pageCache ) )
167
+
168
+ formAction.add_action( CancelAction.new( ribitData, @ribitConfig ) )
169
+ @actionManager.register_action( formAction )
170
+
171
+ categoryFormAction = CategoryFormAction.new( ribitData )
172
+
173
+ categoryFormAction.add_action( SaveCategoryAction.new(
174
+ ribitData,
175
+ @ribitConfig,
176
+ @pageCache ) )
177
+
178
+ categoryFormAction.add_action( CancelCategoryAction.new( ribitData, @ribitConfig ) )
179
+ @actionManager.register_action( categoryFormAction )
180
+
181
+ default = DefaultAction.new( ribitData, @ribitConfig, @pageCache )
182
+ @actionManager.register_action( default )
183
+ @actionManager.set_default_action( default.id )
184
+
185
+ end
186
+ end
187
+
188
+ ##
189
+ #
190
+ class PageRequest
191
+
192
+ #
193
+ def initialize( servletRequest )
194
+ @servletRequest = servletRequest
195
+ @requestParams = parse_query_params( servletRequest.query_string)
196
+ @logger = RibitLogger.new( PageRequest )
197
+ end
198
+
199
+ #
200
+ def get_requested_page_id()
201
+ return @requestParams[Constants::PAGE_ID_REQUEST_PARAM_NAME]
202
+ end
203
+
204
+ #
205
+ def get_query_data
206
+ return @servletRequest.query
207
+ end
208
+ #
209
+ def get_base_path
210
+ return @servletRequest.script_name
211
+ end
212
+
213
+ #
214
+ def get_request_param( name )
215
+ return @requestParams[name]
216
+ return URI.unescape( @requestParams[name] )
217
+ end
218
+
219
+ #
220
+ def get_action_id
221
+ match = /^\/([^\/?]+)/.match( @servletRequest.path_info )
222
+ if ( match == nil )
223
+ return nil
224
+ end
225
+
226
+ return match[1]
227
+ end
228
+
229
+ #
230
+ def get_host
231
+ match = /^((http:\/\/)?[^\/:]+(:[0-9]+)?)/.match( @servletRequest.request_uri.to_s )
232
+ if ( match == nil )
233
+ return '/'
234
+ end
235
+
236
+ return match[1]
237
+ end
238
+
239
+ #
240
+ def get_base_url
241
+ # last '/' is needed otherwise url doesn't work correctly
242
+ return get_host + get_base_path + '/'
243
+ end
244
+
245
+ #
246
+ def get_header_field( name )
247
+ @servletRequest[name]
248
+ end
249
+
250
+ private
251
+ # Parses query parameters and return map containing key-value pairs
252
+ def parse_query_params( queryString )
253
+ # if nothing to parse, return empty hash
254
+ if ( queryString == nil )
255
+ return Hash.new
256
+ end
257
+
258
+ queryString = URI.unescape( queryString )
259
+
260
+ pairs = Array.new
261
+ queryString.each( "&" ) {|s| pairs.push( s ) }
262
+
263
+ map = Hash.new
264
+ pairs.each do |s|
265
+ match = /([^=]+)=([^&]*)/.match( s )
266
+ key = match[1]
267
+ value = match[2]
268
+ map[key] = value
269
+ end
270
+
271
+ return map
272
+ end
273
+
274
+ end
275
+
276
+ ##
277
+ # Wrapper for response object used by Webrick
278
+ class PageResponse
279
+
280
+ #
281
+ def initialize( servletResponse )
282
+ @servletResponse = servletResponse
283
+ end
284
+
285
+ #
286
+ def set_body( data )
287
+ @servletResponse.body = data
288
+ end
289
+
290
+ #
291
+ def get_body
292
+ @servletResponse.body
293
+ end
294
+
295
+ #
296
+ def set_content_type( type )
297
+ @servletResponse['Content-Type'] = type
298
+ end
299
+
300
+ #
301
+ def get_content_type
302
+ @servletResponse['Content-Type']
303
+ end
304
+
305
+ #
306
+ def get_servlet_response
307
+ return @servletResponse
308
+ end
309
+
310
+ #
311
+ def set_header_field( name, value )
312
+ @servletResponse[name] = value
313
+ end
314
+
315
+ #
316
+ def status=(s)
317
+ @servletResponse.status = s
318
+ end
319
+ end
@@ -0,0 +1,909 @@
1
+ #--
2
+ # Copyright (C) 2004-2005 Tero Vuorela
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify it
5
+ # under the terms of the GNU General Public License as published by the Free
6
+ # Software Foundation; either version 2 of the License, or (at your option)
7
+ # any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
+ # more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License along with
15
+ # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16
+ # Place - Suite 330, Boston, MA 02111-1307, USA.
17
+ #++
18
+
19
+ require 'ribit/common'
20
+ require 'common/assert'
21
+ require 'common/properties'
22
+ require "rexml/document"
23
+
24
+ require 'observer'
25
+
26
+ #
27
+ # Class RibitData contains
28
+ # * all pages
29
+ # * all categories
30
+
31
+ # * pages has links to parent categories
32
+ # * categories has links to childs and vice versa
33
+ #
34
+ module RibitData
35
+
36
+ #
37
+ class RibitDataException < RibitException
38
+ end
39
+
40
+ ##
41
+ # This stores categories and individual pages.
42
+ # Pages has unique ID inside one category.
43
+ class Category
44
+ include Observable
45
+
46
+ attr_reader :id, :name, :longName
47
+
48
+ #
49
+ def initialize( id, name, longName )
50
+ @id = id
51
+ @name = name
52
+ @longName = longName
53
+ @pages = Hash.new
54
+ @childCategories = Array.new
55
+ @nextFreePageID = 0
56
+ @parentCategory = nil
57
+ @fullName = '::' + @name
58
+ @properties = Hash.new
59
+ @mainID = nil
60
+ end
61
+
62
+ #
63
+ def add_page( page )
64
+ # check for duplicates
65
+ @pages.values.each do |existingPage|
66
+ if ( page.name == existingPage.name )
67
+ raise RibitDataException, "Page with fullname #{page.full_name} already exists", caller
68
+ end
69
+
70
+ if ( page.id == existingPage.id )
71
+ raise RibitDataException, "Page with ID #{page.full_id} already exists", caller
72
+ end
73
+ end
74
+
75
+ @pages[page.id.to_s] = page
76
+
77
+ if ( page.id.to_i >= @nextFreePageID )
78
+ @nextFreePageID = page.id.to_i + 1
79
+ end
80
+
81
+ changed
82
+ notify_observers( self, 'newPage' )
83
+ end
84
+
85
+ #
86
+ def remove_page( pageID )
87
+ page = @pages.delete( pageID.to_s )
88
+ if ( page != nil )
89
+ changed
90
+ notify_observers( self, 'deletePage', page.full_id )
91
+ end
92
+ end
93
+
94
+ #
95
+ def get_next_free_page_id
96
+ return @nextFreePageID
97
+ end
98
+
99
+ #
100
+ def get_page( pageID )
101
+ return @pages[pageID.to_s]
102
+ end
103
+
104
+ #
105
+ def get_pages
106
+ return @pages.values
107
+ end
108
+
109
+ #
110
+ def get_child_categories
111
+ return @childCategories
112
+ end
113
+
114
+ #
115
+ def toplevel_category?
116
+ return @parentCategory == nil
117
+ end
118
+
119
+ #
120
+ def full_name
121
+ return @fullName
122
+ end
123
+
124
+ #
125
+ def get_parent_category
126
+ return @parentCategory
127
+ end
128
+
129
+ #
130
+ def visible?
131
+ return @properties['visibility'] != 'false'
132
+ end
133
+
134
+ #
135
+ def set_visibility( b )
136
+ @properties['visibility'] = b
137
+ end
138
+
139
+ #
140
+ def set_property( name, value )
141
+ @properties[name] = value
142
+ end
143
+
144
+ # Note: doesn't check does page exists with a id
145
+ def get_main_page_id
146
+ @mainPageID
147
+ end
148
+
149
+ #
150
+ def get_main_page_full_id
151
+
152
+ if ( @mainPageID != nil )
153
+ # check that page exists
154
+ page = get_page( @mainPageID )
155
+ if ( page != nil )
156
+ return page.full_id
157
+ end
158
+ end
159
+
160
+ # main page was not found => select one of pages
161
+
162
+ # if category has no pages we can't return one
163
+ if ( @pages.size == 0 )
164
+ return nil
165
+ end
166
+
167
+ # just take one
168
+
169
+ return get_pages[0].full_id
170
+ end
171
+
172
+ #
173
+ def set_main_page_id( newMainPageID )
174
+ @mainPageID = newMainPageID
175
+ end
176
+
177
+ #
178
+ def to_document
179
+ element = REXML::Element.new( 'category' )
180
+
181
+ shortName = REXML::Element.new( 'short-name' )
182
+ shortName.text = @name
183
+
184
+ longName = REXML::Element.new( 'long-name' )
185
+ longName.text = @longName
186
+
187
+ element.add_element( shortName )
188
+ element.add_element( longName )
189
+
190
+ if ( @mainPageID != nil )
191
+ idEle = REXML::Element.new( 'main-page-id' )
192
+ idEle.text = @mainPageID
193
+ element.add_element( idEle )
194
+ end
195
+
196
+ propertiesEle = REXML::Element.new( 'properties' )
197
+ @properties.each do |key, value|
198
+ propEle = REXML::Element.new( 'property' )
199
+ propEle.attributes['name'] = key
200
+ propEle.attributes['value'] = value
201
+ propertiesEle.add_element( propEle )
202
+ end
203
+
204
+ # Add 'properties' element only if there is data
205
+ if ( propertiesEle.size() > 0 )
206
+ element.add_element( propertiesEle )
207
+ end
208
+
209
+ return element
210
+ end
211
+
212
+ # If category is changed observers are called.
213
+ def set_parent_category( newParentCategory )
214
+ if ( @parentCategory == newParentCategory )
215
+ return
216
+ end
217
+
218
+ # newParentCategory can be nil if there will be no parent (top level category)
219
+
220
+ # check that child can't be set as parent
221
+ if ( newParentCategory != nil and is_descendant( newParentCategory ) )
222
+ raise RibitException, "The category #{newParentCategory.id} can't be parent of #{self.id} because #{newParentCategory.id} is already a child", caller
223
+ end
224
+
225
+ # first remove old ref
226
+ currentParent = self.get_parent_category
227
+ if ( currentParent != nil )
228
+ currentParent.remove_child_category( self )
229
+ end
230
+
231
+ @parentCategory = newParentCategory
232
+ refresh_full_name
233
+
234
+ # then set new one (can be nil)
235
+ if ( newParentCategory != nil )
236
+ newParentCategory.add_child_category( self )
237
+ end
238
+
239
+ changed
240
+ notify_observers( self, 'parentCategory' )
241
+
242
+ end
243
+
244
+ #
245
+ def is_descendant( category )
246
+ @childCategories.each do |childCategory|
247
+ if ( childCategory.id == category.id )
248
+ return true
249
+ end
250
+
251
+ result = childCategory.is_descendant( category )
252
+ if ( result )
253
+ return true
254
+ end
255
+ end
256
+
257
+ # not found => no relationship
258
+ return false
259
+ end
260
+
261
+ # If name changes then Observers are triggered.
262
+ def name=( newName )
263
+ if ( @name == newName )
264
+ return @name
265
+ end
266
+
267
+ @name = newName
268
+ refresh_full_name
269
+ changed
270
+ notify_observers( self, ['name'] )
271
+ end
272
+
273
+ #
274
+ def to_s
275
+ "Category [id=#{@id},name=#{name}]"
276
+ end
277
+
278
+ protected
279
+
280
+ #
281
+ def add_child_category( category )
282
+ @childCategories.push( category )
283
+ end
284
+
285
+ #
286
+ def remove_child_category( category )
287
+ @childCategories.delete( category )
288
+ end
289
+
290
+ # Rebuilds the full_name and calls also childs to do it
291
+ def refresh_full_name
292
+ @fullName = '::' + get_parent_full_name( self )
293
+
294
+ # child also so cache full name => they need to refresh it too
295
+ @childCategories.each do |category|
296
+ category.refresh_full_name
297
+ end
298
+ end
299
+
300
+ private
301
+
302
+ def get_parent_full_name( category )
303
+ if ( category.get_parent_category != nil )
304
+ return get_parent_full_name( category.get_parent_category ) + '::' + category.name
305
+ end
306
+
307
+ return category.name
308
+ end
309
+
310
+
311
+ end
312
+
313
+ ##
314
+ # This class models one page.
315
+ #
316
+ # NOTE:
317
+ # - page id is unique only inside one category
318
+ #
319
+ class Page
320
+ include Assert
321
+ include Observable
322
+
323
+ attr_reader :id, :name, :title, :data, :metadata, :category
324
+
325
+ # TODO: currently title is not different from name
326
+ attr_writer :title
327
+
328
+ #
329
+ def initialize( id, name, category)
330
+ assert_not_nil( id, "id was nil for a page" )
331
+ assert_not_nil( name, "name was nil for page #{id}" )
332
+ assert_not_nil( category, "category was nil for page #{id}" )
333
+
334
+ # allow to use Fixnum (decimal number) as a ID => convert to String
335
+ @id = id.to_s
336
+ @name = name
337
+ @title = name
338
+
339
+ @data = ''
340
+
341
+ # metadata is empty by default
342
+ @metadata = Hash.new
343
+
344
+ @category = category
345
+ @category.add_page( self )
346
+ end
347
+
348
+ # special writer
349
+ def data=( newData )
350
+ if ( !@metadata['modifiable'].to_s == 'false' )
351
+ raise RibitException, "The page #{id} is not modifiable", caller
352
+ end
353
+
354
+ @data = newData
355
+ end
356
+
357
+ # Returns the fullname, category + name separated by ::
358
+ def full_name
359
+ return @category.full_name + "::" + @name
360
+ end
361
+
362
+ # Returns the full id, category.id + page.id separated by ::
363
+ def full_id
364
+ return @category.id.to_s + "::" + @id.to_s
365
+ end
366
+
367
+ # Adds MetaData key-value pair
368
+ def add_metadata( key, value )
369
+ @metadata[key] = value
370
+ end
371
+
372
+ # Returns page data in XML format = REXML::Element
373
+ def to_document
374
+ element = REXML::Element.new( 'page' )
375
+
376
+ # TODO: handle case where data-ref
377
+ name = REXML::Element.new( 'name' )
378
+ title = REXML::Element.new( 'title' )
379
+ data = REXML::Element.new( 'data' )
380
+
381
+ REXML::CData.new( @name, true, name )
382
+ REXML::CData.new( @title, true, title )
383
+ REXML::CData.new( @data, true, data )
384
+
385
+ element.add_element( name )
386
+ element.add_element( title )
387
+ element.add_element( data )
388
+
389
+ metaDataEle = REXML::Element.new( 'metadata' )
390
+ @metadata.each do |key, value|
391
+ propEle = REXML::Element.new( 'property' )
392
+ propEle.attributes['name'] = key
393
+ propEle.attributes['value'] = value
394
+ metaDataEle.add_element( propEle )
395
+ end
396
+
397
+ # Add metadata element only if there is data
398
+ if ( metaDataEle.size() > 0 )
399
+ element.add_element( metaDataEle )
400
+ end
401
+
402
+ return element
403
+ end
404
+
405
+ # This method triggers observer if name is actually different
406
+ def name=( newName )
407
+ # if name is exactly same => do not change
408
+ if ( @name == newName )
409
+ return @name
410
+ end
411
+
412
+ @name = newName
413
+ @title = newName
414
+ changed
415
+ notify_observers( self, ['name' ,'title'] )
416
+ end
417
+
418
+ end # of Page
419
+
420
+
421
+ ##
422
+ # RibitData is toplevel store of page data.
423
+ class RibitData
424
+ include Assert
425
+
426
+ #
427
+ def initialize( dataStorage=nil )
428
+ @pages = Hash.new
429
+ @pagesByName = Hash.new
430
+ @localization = nil
431
+
432
+ @categories = Hash.new
433
+ @categoriesByName = Hash.new
434
+ @nextFreeCategoryID = 0
435
+
436
+ @dataStorage = dataStorage
437
+ end
438
+
439
+ # Getter for page by page fullname (category::name)
440
+ def get_page_by_full_name( fullName )
441
+ # add root mark if needed
442
+ if ( fullName.index( '::' ) != 0 )
443
+ fullName = '::' + fullName
444
+ end
445
+ return @pagesByName[fullName]
446
+ end
447
+
448
+ #
449
+ def get_page_by_id( fullID )
450
+ return @pages[fullID]
451
+ end
452
+
453
+ #
454
+ def add_category( category )
455
+ assert_not_nil( category, 'tried to add nil category' )
456
+
457
+ @categories[category.id] = category
458
+
459
+ if ( @categoriesByName[category.full_name] != nil )
460
+ raise RibitException, "Category with full_name=#{category.full_name} already exists", caller
461
+ end
462
+
463
+ @categoriesByName[category.full_name] = category
464
+ # record pages
465
+ category.get_pages.each do |page|
466
+ add_page( page )
467
+ end
468
+
469
+ if ( category.id.to_i >= @nextFreeCategoryID )
470
+ @nextFreeCategoryID = category.id.to_i + 1
471
+ end
472
+
473
+ category.add_observer( self )
474
+ end
475
+
476
+ #
477
+ def get_all_categories
478
+ @categories.values
479
+ end
480
+
481
+ #
482
+ def get_visible_root_categories
483
+ rootCategories = []
484
+ @categories.values.each do |category|
485
+ if ( category.toplevel_category? and category.visible? )
486
+ rootCategories.push( category )
487
+ end
488
+ end
489
+
490
+ return rootCategories
491
+ end
492
+
493
+ #
494
+ def get_category_by_id( id )
495
+ return @categories[id]
496
+ end
497
+
498
+ #
499
+ def get_category_by_full_name( name )
500
+ # add root mark if needed
501
+ if ( name.index( '::' ) != 0 )
502
+ name = '::' + name
503
+ end
504
+ return @categoriesByName[name]
505
+ end
506
+
507
+ #
508
+ def get_next_free_category_id
509
+ return @nextFreeCategoryID
510
+ end
511
+
512
+ # Returns the Properties object that contain localization key-value pairs.
513
+ def get_localization
514
+ if ( @localization == nil )
515
+ page = get_page_by_full_name( '::core::localizationdata' )
516
+ if ( page == nil )
517
+ raise RibitDataException, 'No localization data found', caller
518
+ end
519
+
520
+ prop = Properties.new
521
+ prop.load( page.data )
522
+
523
+ @localization = prop
524
+ end
525
+
526
+ return @localization
527
+ end
528
+
529
+ # Returns true if 'data' is fullName of a page. If 'data'
530
+ # contains string '::' then it is considered to be full name.
531
+ def RibitData.fullname?( data )
532
+ return data.to_s.index( '::' ) != nil
533
+ end
534
+
535
+ #
536
+ def update( obj, namesOfChangedProperties, id=nil )
537
+ if ( obj.kind_of?( Page ) )
538
+ # what have changed, for pages we are interested: name
539
+
540
+ if ( namesOfChangedProperties.include?( 'name' ) )
541
+ refresh_maps_by_name
542
+ end
543
+
544
+ elsif ( obj.kind_of?( Category ) )
545
+
546
+ if ( namesOfChangedProperties.include?( 'name' ) )
547
+ refresh_maps_by_name
548
+
549
+ elsif ( namesOfChangedProperties.include?( 'parentCategory' ) )
550
+ refresh_maps_by_name
551
+
552
+ elsif ( namesOfChangedProperties.include?( 'newPage' ) )
553
+
554
+ obj.get_pages.each do |page|
555
+ if ( get_page_by_id( page.full_id ) == nil )
556
+ # this page has not been recorded before => record it
557
+ add_page( page )
558
+ end
559
+ end
560
+ elsif ( namesOfChangedProperties.include?( 'deletePage' ) )
561
+ assert_not_nil( id )
562
+ page = @pages[id]
563
+ @pagesByName.delete( page.full_name )
564
+ @pages.delete( page.full_id )
565
+ end
566
+ end
567
+
568
+ end
569
+
570
+ #
571
+ def create_category( name, longName, parentCategory )
572
+ catID = get_next_free_category_id()
573
+ category = Category.new( catID, name, longName )
574
+ category.set_parent_category( parentCategory ) unless parentCategory == nil
575
+
576
+ # ribitData throws exception if we try to add duplicates
577
+ add_category( category )
578
+
579
+ # next create category specific files
580
+ @dataStorage.save_category( category )
581
+
582
+ @dataStorage.save_categories_hierarchy( self )
583
+
584
+ return category
585
+ end
586
+
587
+ #
588
+ def save_page( page )
589
+ if ( @dataStorage == nil )
590
+ raise RibitException, 'dataStorage has not been defined', caller
591
+ end
592
+
593
+ @dataStorage.save_page( page )
594
+ end
595
+
596
+ #
597
+ def save_category( category )
598
+ if ( @dataStorage == nil )
599
+ raise RibitException, 'dataStorage has not been defined', caller
600
+ end
601
+
602
+ @dataStorage.save_category( category )
603
+ end
604
+
605
+ #
606
+ def save_categories_hierarchy
607
+ if ( @dataStorage == nil )
608
+ raise RibitException, 'dataStorage has not been defined', caller
609
+ end
610
+
611
+ @dataStorage.save_categories_hierarchy( self )
612
+ end
613
+
614
+ protected
615
+
616
+ #
617
+ def refresh_maps_by_name
618
+ @pagesByName.clear
619
+ @categoriesByName.clear
620
+
621
+ @categories.values.each do |category|
622
+ @categoriesByName[category.full_name] = category
623
+ end
624
+ #print( "\nall cats by name: " + @categoriesByName.to_s )
625
+ @pages.values.each do |page|
626
+ @pagesByName[page.full_name] = page
627
+ end
628
+
629
+ end
630
+
631
+ # Adds a new page, raises if ID or fullname is already used
632
+ def add_page( page )
633
+ fullName = page.full_name
634
+ if ( @pagesByName[fullName] != nil )
635
+ raise RibitDataException, "Page with fullname #{fullName} already exists", caller
636
+ end
637
+ @pagesByName[fullName] = page
638
+
639
+ fullID = page.full_id
640
+ if ( @pages[fullID] != nil )
641
+ raise RibitDataException, "Page with ID #{fullID} already exists", caller
642
+ end
643
+ @pages[fullID] = page
644
+
645
+ # we like to know from changes (name is used in maps)
646
+ page.add_observer( self )
647
+ end
648
+
649
+ end
650
+
651
+
652
+ ##
653
+ #
654
+ class CategoryParser
655
+ CATEGORIES_XML_FILE = 'categories.xml'
656
+ CATEGORY_XML_FILE = 'category.xml'
657
+
658
+ #
659
+ def initialize( contentDirectory )
660
+ @contentDir = contentDirectory
661
+ end
662
+
663
+ #
664
+ def parse_categories
665
+ categoriesXML = File.new( File.join( @contentDir, CATEGORIES_XML_FILE ) )
666
+ categories = Array.new
667
+ begin
668
+ doc = REXML::Document.new( categoriesXML )
669
+ doc.elements.each( 'categories/category' ) do |topLevelCategory|
670
+ categories.push( process_category_ele( topLevelCategory ) )
671
+ end
672
+
673
+ return categories
674
+ ensure
675
+ categoriesXML.close
676
+ end
677
+ end
678
+
679
+ #
680
+ def process_category_ele( categoryElement )
681
+ #puts '########## ' + categoryElement.to_s
682
+ catID = categoryElement.attributes['id']
683
+ #puts '########## ID = ' + catID
684
+ category = parse_category( catID )
685
+
686
+ # is there subcategories ?
687
+ if ( categoryElement.elements['category'] != nil )
688
+ categoryElement.get_elements( 'category' ).each do |subCategoryEle|
689
+ subCategory = process_category_ele( subCategoryEle )
690
+ subCategory.set_parent_category( category )
691
+ end
692
+ end
693
+
694
+ return category
695
+ end
696
+
697
+ #
698
+ def parse_category( categoryID )
699
+ categoryDir = File.join( @contentDir, categoryID )
700
+
701
+ # first read category.xml
702
+ categoryXML = File.new( File.join( categoryDir, CATEGORY_XML_FILE ) )
703
+
704
+ begin
705
+ return parse_category_doc( categoryID, categoryXML )
706
+ ensure
707
+ categoryXML.close
708
+ end
709
+ end
710
+
711
+ #
712
+ def parse_category_doc( categoryID, categoryXML )
713
+ doc = REXML::Document.new( categoryXML )
714
+ shortName = categoryID
715
+ longName = categoryID
716
+
717
+ doc.elements.each( 'category/short-name' ) do |ele|
718
+ shortName = ele.text
719
+ end
720
+
721
+ doc.elements.each( 'category/long-name' ) do |ele|
722
+ longName = ele.text
723
+ end
724
+
725
+ mainPageID = nil
726
+ doc.elements.each( 'category/main-page-id' ) do |ele|
727
+ mainPageID = ele.text
728
+ end
729
+
730
+ category = Category.new( categoryID, shortName, longName )
731
+ category.set_main_page_id( mainPageID )
732
+
733
+ properties = Hash.new
734
+ doc.elements.each("category/properties/property" ) do |property|
735
+ name = property.attributes["name"]
736
+ value = property.attributes["value"]
737
+ category.set_property( name, value )
738
+ end
739
+
740
+ return category
741
+ end
742
+ end
743
+
744
+ #
745
+ class CategoriesWriter
746
+
747
+ #
748
+ def initialize( ribitData )
749
+ @ribitData = ribitData
750
+ end
751
+
752
+ #
753
+ def to_document
754
+ element = REXML::Element.new( 'categories' )
755
+
756
+ @ribitData.get_all_categories.each do |category|
757
+ # we build hierarchial structure but ribitData contains all categories
758
+ if ( category.toplevel_category? )
759
+ element.add_element( get_category_element( category ) )
760
+ end
761
+ end
762
+
763
+ return element
764
+ end
765
+
766
+ #
767
+ def get_category_element( category )
768
+ element = REXML::Element.new( 'category' )
769
+ element.attributes['id'] = category.id
770
+
771
+ category.get_child_categories.each do |child|
772
+ element.add_element( get_category_element( child ) )
773
+ end
774
+ return element
775
+ end
776
+
777
+ end
778
+
779
+ ##
780
+ #
781
+ class PageParser
782
+
783
+ #
784
+ def initialize( contentDirectory )
785
+ @contentDir = contentDirectory
786
+ @logger = RibitLogger.new( PageParser )
787
+ end
788
+
789
+ #
790
+ def parse_pages( category )
791
+ @logger.debug( "Parsing pages for category #{category.name}" )
792
+ categoryDir = File.join( @contentDir, category.id )
793
+ @logger.debug( "Looking *.xml files from #{categoryDir}" )
794
+ pages = Array.new
795
+ # under category dir all those files with <number>.xml are page files
796
+ Dir[File.join( categoryDir, '*.xml')].each do |fileName|
797
+ @logger.debug( "Found #{fileName}" )
798
+ if ( /^[0-9]+\.xml$/.match( File.basename( fileName ) ) )
799
+ # yes, the name matches
800
+ pages.push( parse_page( category, fileName ) )
801
+ end
802
+
803
+ end
804
+
805
+ return pages
806
+ end
807
+
808
+ # Parses an XML file and returns instance of Page
809
+ def parse_page( category, fileName )
810
+ @logger.debug( "Parsing page data from file #{fileName}" )
811
+ @file = File.new( fileName )
812
+ begin
813
+ doc = REXML::Document.new( @file )
814
+ id = File.basename( fileName, ".xml")
815
+ # looped only once
816
+ doc.elements.each do |pageEle|
817
+ name = getText( pageEle.elements['name'] )
818
+ page = Page.new( id, name, category )
819
+ page.title = getText( pageEle.elements['title'] )
820
+ page.data = getText( pageEle.elements['data'] )
821
+
822
+ pageEle.elements.each("meta/property" ) do |properties|
823
+ name = properties.attributes["name"]
824
+ value = properties.attributes["value"]
825
+ page.add_metadata( name, value )
826
+ end
827
+
828
+ @logger.debug( "Read the page ID=#{page.full_id}, name=#{page.full_name}" )
829
+ return page
830
+ end
831
+ ensure
832
+ @file.close
833
+ end
834
+
835
+ end
836
+
837
+ # Returns true if page can be modified
838
+ def page_modifiable?( element )
839
+ dataEle = element.elements['data']
840
+
841
+ # page can't be modified if it refers to a file
842
+ return dataEle.attributes['file-ref'] == nil
843
+ end
844
+
845
+ # Returns text data from the provided XML element.
846
+ private
847
+ def getText( element )
848
+ if ( element != nil )
849
+ if ( element.attributes['file-ref'] != nil )
850
+ # we have reference to a file
851
+ fileName = element.attributes['file-ref']
852
+
853
+ # first try if the path is absolute
854
+ if ( !File.exist?( fileName ) )
855
+ # wasn't absolute => try relative path
856
+ relativePath = File.join( File.dirname( @file.path ), fileName )
857
+ if ( !File.exist?( relativePath ) )
858
+ errorText = "Error: File not found. Tried #{fileName} and #{relativePath}"
859
+ raise RibitException, errorText, caller
860
+ end
861
+
862
+ fileName = relativePath
863
+ end
864
+
865
+ # -- now we know file exists
866
+
867
+ # read the whole file
868
+ data = ""
869
+ File.open( fileName, 'r' ) do |f|
870
+ data << f.read
871
+ end
872
+
873
+ if ( data.size == 0 )
874
+ # this case is legal but still could to log
875
+ @logger.warn( "No data in file #{fileName}" )
876
+ end
877
+
878
+ return data
879
+ else
880
+ return element.text
881
+ end
882
+ end
883
+ # return nil if there is no data to return
884
+ return nil
885
+ end
886
+
887
+ end # of PageParser
888
+
889
+ end # end of RibitData module
890
+
891
+
892
+ # TODO: better name confuses to datastorage
893
+ module IDataStorage
894
+
895
+ # This method saves the page and does reloading if needed
896
+ def save_page( page )
897
+ raise RuntimeError, 'load_page() not implemented', caller
898
+ end
899
+
900
+ #
901
+ def save_category( category )
902
+ raise RuntimeError, 'load_category() not implemented', caller
903
+ end
904
+
905
+ #
906
+ def save_categories_hierarchy( ribitData )
907
+ raise RuntimeError, 'save_categories_hierarchy() not implemented', caller
908
+ end
909
+ end