ribit 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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