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.
- data/INSTALL +52 -0
- data/LICENSE +343 -0
- data/README +42 -0
- data/bin/ribit +26 -0
- data/bin/ribit-setup +153 -0
- data/bin/ribitd +18 -0
- data/doc/TODO.txt +207 -0
- data/doc/devdiary.txt +258 -0
- data/doc/diagrams/content-classes.dia +0 -0
- data/doc/diagrams/main-classes.dia +0 -0
- data/doc/diagrams/page-rendering-classes.dia +0 -0
- data/doc/diagrams/ribitservlet-classes.dia +0 -0
- data/doc/examples/xhtml-example.html +64 -0
- data/doc/notes.txt +7 -0
- data/doc/rdoc/classes/ActionAdapter.html +137 -0
- data/doc/rdoc/classes/ActionAdapter.src/M000160.html +26 -0
- data/doc/rdoc/classes/ActionElement.html +179 -0
- data/doc/rdoc/classes/ActionElement.src/M000204.html +19 -0
- data/doc/rdoc/classes/ActionElement.src/M000205.html +18 -0
- data/doc/rdoc/classes/ActionManager.html +187 -0
- data/doc/rdoc/classes/ActionManager.src/M000237.html +19 -0
- data/doc/rdoc/classes/ActionManager.src/M000238.html +22 -0
- data/doc/rdoc/classes/ActionManager.src/M000239.html +22 -0
- data/doc/rdoc/classes/ActionManager.src/M000240.html +23 -0
- data/doc/rdoc/classes/Assert.html +229 -0
- data/doc/rdoc/classes/Assert.src/M000369.html +20 -0
- data/doc/rdoc/classes/Assert.src/M000370.html +18 -0
- data/doc/rdoc/classes/Assert.src/M000371.html +20 -0
- data/doc/rdoc/classes/Assert.src/M000372.html +18 -0
- data/doc/rdoc/classes/Assert.src/M000373.html +20 -0
- data/doc/rdoc/classes/Assert.src/M000374.html +18 -0
- data/doc/rdoc/classes/Assert.src/M000375.html +22 -0
- data/doc/rdoc/classes/Assert/AssertionFailedException.html +117 -0
- data/doc/rdoc/classes/BaseTag.html +166 -0
- data/doc/rdoc/classes/BaseTag.src/M000049.html +20 -0
- data/doc/rdoc/classes/BoldContainer.html +139 -0
- data/doc/rdoc/classes/BoldContainer.src/M000164.html +18 -0
- data/doc/rdoc/classes/BoldParser.html +156 -0
- data/doc/rdoc/classes/BoldParser.src/M000247.html +18 -0
- data/doc/rdoc/classes/BoldParser.src/M000248.html +18 -0
- data/doc/rdoc/classes/CachedPage.html +187 -0
- data/doc/rdoc/classes/CachedPage.src/M000244.html +20 -0
- data/doc/rdoc/classes/CachedPage.src/M000245.html +27 -0
- data/doc/rdoc/classes/CachedPage.src/M000246.html +18 -0
- data/doc/rdoc/classes/CancelAction.html +179 -0
- data/doc/rdoc/classes/CancelAction.src/M000165.html +22 -0
- data/doc/rdoc/classes/CancelAction.src/M000166.html +20 -0
- data/doc/rdoc/classes/CancelAction.src/M000167.html +21 -0
- data/doc/rdoc/classes/CancelCategoryAction.html +164 -0
- data/doc/rdoc/classes/CancelCategoryAction.src/M000115.html +22 -0
- data/doc/rdoc/classes/CancelCategoryAction.src/M000116.html +20 -0
- data/doc/rdoc/classes/CategoriesPage.html +212 -0
- data/doc/rdoc/classes/CategoriesPage.src/M000232.html +27 -0
- data/doc/rdoc/classes/CategoriesPage.src/M000233.html +18 -0
- data/doc/rdoc/classes/CategoriesPage.src/M000234.html +73 -0
- data/doc/rdoc/classes/CategoriesPage.src/M000235.html +29 -0
- data/doc/rdoc/classes/CategoriesPage.src/M000236.html +59 -0
- data/doc/rdoc/classes/CategoryBarActionElement.html +139 -0
- data/doc/rdoc/classes/CategoryBarActionElement.src/M000069.html +18 -0
- data/doc/rdoc/classes/CategoryBarNextLevelActionElement.html +139 -0
- data/doc/rdoc/classes/CategoryBarNextLevelActionElement.src/M000026.html +18 -0
- data/doc/rdoc/classes/CategoryFormAction.html +169 -0
- data/doc/rdoc/classes/CategoryFormAction.src/M000148.html +18 -0
- data/doc/rdoc/classes/CategoryFormAction.src/M000149.html +30 -0
- data/doc/rdoc/classes/CategoryFormActionAdapter.html +171 -0
- data/doc/rdoc/classes/CategoryFormActionAdapter.src/M000112.html +19 -0
- data/doc/rdoc/classes/CategoryFormActionAdapter.src/M000113.html +18 -0
- data/doc/rdoc/classes/CategoryFormActionAdapter.src/M000114.html +18 -0
- data/doc/rdoc/classes/CompositeAction.html +186 -0
- data/doc/rdoc/classes/CompositeAction.src/M000119.html +19 -0
- data/doc/rdoc/classes/CompositeAction.src/M000120.html +18 -0
- data/doc/rdoc/classes/CompositeAction.src/M000121.html +21 -0
- data/doc/rdoc/classes/CompositeAction.src/M000122.html +18 -0
- data/doc/rdoc/classes/CompositeLinkActionElement.html +156 -0
- data/doc/rdoc/classes/CompositeLinkActionElement.src/M000196.html +20 -0
- data/doc/rdoc/classes/CompositeLinkActionElement.src/M000197.html +41 -0
- data/doc/rdoc/classes/Constants.html +198 -0
- data/doc/rdoc/classes/Container.html +281 -0
- data/doc/rdoc/classes/Container.src/M000251.html +19 -0
- data/doc/rdoc/classes/Container.src/M000252.html +18 -0
- data/doc/rdoc/classes/Container.src/M000253.html +18 -0
- data/doc/rdoc/classes/Container.src/M000254.html +18 -0
- data/doc/rdoc/classes/Container.src/M000255.html +27 -0
- data/doc/rdoc/classes/Container.src/M000256.html +18 -0
- data/doc/rdoc/classes/Container.src/M000257.html +18 -0
- data/doc/rdoc/classes/Container.src/M000258.html +18 -0
- data/doc/rdoc/classes/Container.src/M000259.html +18 -0
- data/doc/rdoc/classes/Container.src/M000260.html +23 -0
- data/doc/rdoc/classes/ContentDoc.html +236 -0
- data/doc/rdoc/classes/ContentDoc.src/M000129.html +22 -0
- data/doc/rdoc/classes/ContentDoc.src/M000130.html +18 -0
- data/doc/rdoc/classes/ContentDoc.src/M000131.html +20 -0
- data/doc/rdoc/classes/ContentDoc.src/M000132.html +18 -0
- data/doc/rdoc/classes/ContentDoc.src/M000133.html +18 -0
- data/doc/rdoc/classes/ContentDoc.src/M000134.html +18 -0
- data/doc/rdoc/classes/ContentDoc.src/M000135.html +18 -0
- data/doc/rdoc/classes/ContentParser.html +176 -0
- data/doc/rdoc/classes/ContentParser.src/M000176.html +30 -0
- data/doc/rdoc/classes/ContentParser.src/M000177.html +28 -0
- data/doc/rdoc/classes/ContentParser.src/M000178.html +55 -0
- data/doc/rdoc/classes/CurrentList.html +209 -0
- data/doc/rdoc/classes/CurrentList.src/M000228.html +19 -0
- data/doc/rdoc/classes/CurrentList.src/M000229.html +18 -0
- data/doc/rdoc/classes/CurrentList.src/M000230.html +18 -0
- data/doc/rdoc/classes/CurrentList.src/M000231.html +18 -0
- data/doc/rdoc/classes/DataContainer.html +234 -0
- data/doc/rdoc/classes/DataContainer.src/M000101.html +26 -0
- data/doc/rdoc/classes/DataContainer.src/M000102.html +24 -0
- data/doc/rdoc/classes/DataContainer.src/M000103.html +23 -0
- data/doc/rdoc/classes/DataContainer.src/M000104.html +26 -0
- data/doc/rdoc/classes/DataContainer.src/M000105.html +22 -0
- data/doc/rdoc/classes/DataContainer.src/M000106.html +18 -0
- data/doc/rdoc/classes/DataStorage.html +199 -0
- data/doc/rdoc/classes/DataStorage.src/M000031.html +23 -0
- data/doc/rdoc/classes/DataStorage.src/M000032.html +36 -0
- data/doc/rdoc/classes/DataStorage.src/M000033.html +25 -0
- data/doc/rdoc/classes/DataStorage.src/M000034.html +30 -0
- data/doc/rdoc/classes/DataStorage.src/M000035.html +21 -0
- data/doc/rdoc/classes/DefaultAction.html +187 -0
- data/doc/rdoc/classes/DefaultAction.src/M000014.html +23 -0
- data/doc/rdoc/classes/DefaultAction.src/M000015.html +36 -0
- data/doc/rdoc/classes/DefaultAction.src/M000016.html +38 -0
- data/doc/rdoc/classes/DefaultLoggerFactory.html +140 -0
- data/doc/rdoc/classes/DefaultLoggerFactory.src/M000169.html +19 -0
- data/doc/rdoc/classes/DirectLinkContainer.html +156 -0
- data/doc/rdoc/classes/DirectLinkContainer.src/M000209.html +19 -0
- data/doc/rdoc/classes/DirectLinkContainer.src/M000210.html +18 -0
- data/doc/rdoc/classes/DirectLinkParser.html +137 -0
- data/doc/rdoc/classes/DirectLinkParser.src/M000168.html +39 -0
- data/doc/rdoc/classes/DivTag.html +150 -0
- data/doc/rdoc/classes/DivTag.src/M000030.html +19 -0
- data/doc/rdoc/classes/EditAction.html +177 -0
- data/doc/rdoc/classes/EditAction.src/M000056.html +24 -0
- data/doc/rdoc/classes/EditAction.src/M000057.html +64 -0
- data/doc/rdoc/classes/EditActionAdapter.html +139 -0
- data/doc/rdoc/classes/EditActionAdapter.src/M000002.html +20 -0
- data/doc/rdoc/classes/EditCategoryAction.html +176 -0
- data/doc/rdoc/classes/EditCategoryAction.src/M000126.html +24 -0
- data/doc/rdoc/classes/EditCategoryAction.src/M000127.html +39 -0
- data/doc/rdoc/classes/EditCategoryActionAdapter.html +139 -0
- data/doc/rdoc/classes/EditCategoryActionAdapter.src/M000021.html +20 -0
- data/doc/rdoc/classes/EditCategoryPage.html +242 -0
- data/doc/rdoc/classes/EditCategoryPage.src/M000036.html +29 -0
- data/doc/rdoc/classes/EditCategoryPage.src/M000037.html +18 -0
- data/doc/rdoc/classes/EditCategoryPage.src/M000038.html +18 -0
- data/doc/rdoc/classes/EditCategoryPage.src/M000039.html +18 -0
- data/doc/rdoc/classes/EditCategoryPage.src/M000040.html +109 -0
- data/doc/rdoc/classes/EditCategoryPage.src/M000041.html +60 -0
- data/doc/rdoc/classes/EditCategoryPage.src/M000042.html +29 -0
- data/doc/rdoc/classes/EditNewActionAdapter.html +156 -0
- data/doc/rdoc/classes/EditNewActionAdapter.src/M000220.html +20 -0
- data/doc/rdoc/classes/EditNewActionAdapter.src/M000221.html +23 -0
- data/doc/rdoc/classes/EditPage.html +212 -0
- data/doc/rdoc/classes/EditPage.src/M000064.html +33 -0
- data/doc/rdoc/classes/EditPage.src/M000065.html +18 -0
- data/doc/rdoc/classes/EditPage.src/M000066.html +18 -0
- data/doc/rdoc/classes/EditPage.src/M000067.html +18 -0
- data/doc/rdoc/classes/EditPage.src/M000068.html +112 -0
- data/doc/rdoc/classes/EmphasisContainer.html +156 -0
- data/doc/rdoc/classes/EmphasisContainer.src/M000003.html +20 -0
- data/doc/rdoc/classes/EmphasisContainer.src/M000004.html +19 -0
- data/doc/rdoc/classes/EmphasisParser.html +176 -0
- data/doc/rdoc/classes/EmphasisParser.src/M000076.html +19 -0
- data/doc/rdoc/classes/EmphasisParser.src/M000077.html +18 -0
- data/doc/rdoc/classes/EmphasisParser.src/M000078.html +45 -0
- data/doc/rdoc/classes/EscapeParser.html +137 -0
- data/doc/rdoc/classes/EscapeParser.src/M000150.html +26 -0
- data/doc/rdoc/classes/ExpireMetaTag.html +139 -0
- data/doc/rdoc/classes/ExpireMetaTag.src/M000241.html +18 -0
- data/doc/rdoc/classes/FilePersistentStorageHandler.html +207 -0
- data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000215.html +27 -0
- data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000216.html +21 -0
- data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000217.html +19 -0
- data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000218.html +19 -0
- data/doc/rdoc/classes/FilePersistentStorageHandler.src/M000219.html +20 -0
- data/doc/rdoc/classes/FormAction.html +169 -0
- data/doc/rdoc/classes/FormAction.src/M000081.html +18 -0
- data/doc/rdoc/classes/FormAction.src/M000082.html +30 -0
- data/doc/rdoc/classes/FormActionAdapter.html +171 -0
- data/doc/rdoc/classes/FormActionAdapter.src/M000086.html +19 -0
- data/doc/rdoc/classes/FormActionAdapter.src/M000087.html +18 -0
- data/doc/rdoc/classes/FormActionAdapter.src/M000088.html +18 -0
- data/doc/rdoc/classes/FormActionElement.html +169 -0
- data/doc/rdoc/classes/FormActionElement.src/M000044.html +18 -0
- data/doc/rdoc/classes/FormActionElement.src/M000045.html +18 -0
- data/doc/rdoc/classes/FormActionElement.src/M000046.html +23 -0
- data/doc/rdoc/classes/FormInputTag.html +165 -0
- data/doc/rdoc/classes/FormInputTag.src/M000161.html +21 -0
- data/doc/rdoc/classes/HiddenFormInputTag.html +139 -0
- data/doc/rdoc/classes/HiddenFormInputTag.src/M000027.html +18 -0
- data/doc/rdoc/classes/IDataStorage.html +170 -0
- data/doc/rdoc/classes/IDataStorage.src/M000382.html +18 -0
- data/doc/rdoc/classes/IDataStorage.src/M000383.html +18 -0
- data/doc/rdoc/classes/IDataStorage.src/M000384.html +18 -0
- data/doc/rdoc/classes/ItalicContainer.html +139 -0
- data/doc/rdoc/classes/ItalicContainer.src/M000128.html +18 -0
- data/doc/rdoc/classes/ItalicParser.html +156 -0
- data/doc/rdoc/classes/ItalicParser.src/M000207.html +18 -0
- data/doc/rdoc/classes/ItalicParser.src/M000208.html +18 -0
- data/doc/rdoc/classes/LinkActionElement.html +184 -0
- data/doc/rdoc/classes/LinkActionElement.src/M000005.html +18 -0
- data/doc/rdoc/classes/LinkActionElement.src/M000006.html +18 -0
- data/doc/rdoc/classes/LinkActionElement.src/M000007.html +18 -0
- data/doc/rdoc/classes/LinkActionElement.src/M000008.html +18 -0
- data/doc/rdoc/classes/LinkTag.html +187 -0
- data/doc/rdoc/classes/LinkTag.src/M000153.html +34 -0
- data/doc/rdoc/classes/LinkTag.src/M000154.html +18 -0
- data/doc/rdoc/classes/LinkTag.src/M000155.html +20 -0
- data/doc/rdoc/classes/ListContainer.html +156 -0
- data/doc/rdoc/classes/ListContainer.src/M000174.html +18 -0
- data/doc/rdoc/classes/ListContainer.src/M000175.html +19 -0
- data/doc/rdoc/classes/ListItemContainer.html +156 -0
- data/doc/rdoc/classes/ListItemContainer.src/M000028.html +19 -0
- data/doc/rdoc/classes/ListItemContainer.src/M000029.html +19 -0
- data/doc/rdoc/classes/ListParser.html +144 -0
- data/doc/rdoc/classes/ListParser.src/M000195.html +147 -0
- data/doc/rdoc/classes/ListParserUtils.html +141 -0
- data/doc/rdoc/classes/ListParserUtils.src/M000385.html +23 -0
- data/doc/rdoc/classes/Localization.html +209 -0
- data/doc/rdoc/classes/Localization.src/M000311.html +40 -0
- data/doc/rdoc/classes/Localization.src/M000312.html +23 -0
- data/doc/rdoc/classes/Log4r.html +111 -0
- data/doc/rdoc/classes/Log4r/ExtendedRollingFileOutputter.html +178 -0
- data/doc/rdoc/classes/Log4r/ExtendedRollingFileOutputter.src/M000380.html +25 -0
- data/doc/rdoc/classes/Log4r/ExtendedRollingFileOutputter.src/M000381.html +33 -0
- data/doc/rdoc/classes/LoggerFactory.html +152 -0
- data/doc/rdoc/classes/LoggerFactory.src/M000062.html +22 -0
- data/doc/rdoc/classes/LoggerFactory.src/M000063.html +18 -0
- data/doc/rdoc/classes/MetaTag.html +166 -0
- data/doc/rdoc/classes/MetaTag.src/M000118.html +20 -0
- data/doc/rdoc/classes/NoCacheMetaTag.html +139 -0
- data/doc/rdoc/classes/NoCacheMetaTag.src/M000043.html +18 -0
- data/doc/rdoc/classes/PageRequest.html +259 -0
- data/doc/rdoc/classes/PageRequest.src/M000179.html +20 -0
- data/doc/rdoc/classes/PageRequest.src/M000180.html +18 -0
- data/doc/rdoc/classes/PageRequest.src/M000181.html +18 -0
- data/doc/rdoc/classes/PageRequest.src/M000182.html +18 -0
- data/doc/rdoc/classes/PageRequest.src/M000183.html +19 -0
- data/doc/rdoc/classes/PageRequest.src/M000184.html +23 -0
- data/doc/rdoc/classes/PageRequest.src/M000185.html +23 -0
- data/doc/rdoc/classes/PageRequest.src/M000186.html +19 -0
- data/doc/rdoc/classes/PageRequest.src/M000187.html +18 -0
- data/doc/rdoc/classes/PageResponse.html +250 -0
- data/doc/rdoc/classes/PageResponse.src/M000092.html +18 -0
- data/doc/rdoc/classes/PageResponse.src/M000093.html +18 -0
- data/doc/rdoc/classes/PageResponse.src/M000094.html +18 -0
- data/doc/rdoc/classes/PageResponse.src/M000095.html +18 -0
- data/doc/rdoc/classes/PageResponse.src/M000096.html +18 -0
- data/doc/rdoc/classes/PageResponse.src/M000097.html +18 -0
- data/doc/rdoc/classes/PageResponse.src/M000098.html +18 -0
- data/doc/rdoc/classes/PageResponse.src/M000099.html +18 -0
- data/doc/rdoc/classes/ParagraphContainer.html +156 -0
- data/doc/rdoc/classes/ParagraphContainer.src/M000158.html +19 -0
- data/doc/rdoc/classes/ParagraphContainer.src/M000159.html +24 -0
- data/doc/rdoc/classes/ParagraphParser.html +137 -0
- data/doc/rdoc/classes/ParagraphParser.src/M000151.html +42 -0
- data/doc/rdoc/classes/PersistentStorageHandler.html +182 -0
- data/doc/rdoc/classes/PersistentStorageHandler.src/M000376.html +18 -0
- data/doc/rdoc/classes/PersistentStorageHandler.src/M000377.html +18 -0
- data/doc/rdoc/classes/PersistentStorageHandler.src/M000378.html +18 -0
- data/doc/rdoc/classes/PersistentStorageHandler.src/M000379.html +18 -0
- data/doc/rdoc/classes/Pid.html +182 -0
- data/doc/rdoc/classes/Pid.src/M000083.html +18 -0
- data/doc/rdoc/classes/Pid.src/M000084.html +24 -0
- data/doc/rdoc/classes/Pid.src/M000085.html +18 -0
- data/doc/rdoc/classes/Properties.html +184 -0
- data/doc/rdoc/classes/Properties.src/M000058.html +18 -0
- data/doc/rdoc/classes/Properties.src/M000059.html +18 -0
- data/doc/rdoc/classes/Properties.src/M000060.html +18 -0
- data/doc/rdoc/classes/Properties.src/M000061.html +27 -0
- data/doc/rdoc/classes/PropertyList.html +187 -0
- data/doc/rdoc/classes/PropertyList.src/M000017.html +19 -0
- data/doc/rdoc/classes/PropertyList.src/M000018.html +23 -0
- data/doc/rdoc/classes/PropertyList.src/M000019.html +23 -0
- data/doc/rdoc/classes/PropertyList.src/M000020.html +18 -0
- data/doc/rdoc/classes/RawAttribute.html +154 -0
- data/doc/rdoc/classes/RawAttribute.src/M000249.html +20 -0
- data/doc/rdoc/classes/RawAttribute.src/M000250.html +21 -0
- data/doc/rdoc/classes/RawPage.html +171 -0
- data/doc/rdoc/classes/RawPage.src/M000107.html +19 -0
- data/doc/rdoc/classes/RawPage.src/M000108.html +18 -0
- data/doc/rdoc/classes/RawPage.src/M000109.html +18 -0
- data/doc/rdoc/classes/ReferenceLinkContainer.html +156 -0
- data/doc/rdoc/classes/ReferenceLinkContainer.src/M000213.html +20 -0
- data/doc/rdoc/classes/ReferenceLinkContainer.src/M000214.html +19 -0
- data/doc/rdoc/classes/Ribit.html +124 -0
- data/doc/rdoc/classes/Ribit/ContentStore.html +236 -0
- data/doc/rdoc/classes/Ribit/ContentStore.src/M000304.html +23 -0
- data/doc/rdoc/classes/Ribit/ContentStore.src/M000305.html +29 -0
- data/doc/rdoc/classes/Ribit/ContentStore.src/M000306.html +25 -0
- data/doc/rdoc/classes/Ribit/ContentStore.src/M000307.html +49 -0
- data/doc/rdoc/classes/Ribit/ContentStore.src/M000308.html +18 -0
- data/doc/rdoc/classes/Ribit/ContentStore.src/M000309.html +73 -0
- data/doc/rdoc/classes/Ribit/ContentStore.src/M000310.html +51 -0
- data/doc/rdoc/classes/Ribit/FileWriter.html +162 -0
- data/doc/rdoc/classes/Ribit/FileWriter.src/M000289.html +19 -0
- data/doc/rdoc/classes/Ribit/FileWriter.src/M000290.html +32 -0
- data/doc/rdoc/classes/Ribit/Repository.html +174 -0
- data/doc/rdoc/classes/Ribit/Repository.src/M000276.html +18 -0
- data/doc/rdoc/classes/Ribit/Repository.src/M000277.html +18 -0
- data/doc/rdoc/classes/Ribit/Repository.src/M000278.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLogger.html +137 -0
- data/doc/rdoc/classes/Ribit/RibitLogger.src/M000301.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerConfig.html +182 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerConfig.src/M000279.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerConfig.src/M000280.html +23 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerConfig.src/M000281.html +21 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerConfig.src/M000282.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerFactory.html +154 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerFactory.src/M000287.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerFactory.src/M000288.html +25 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerImpl.html +229 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000294.html +26 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000295.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000296.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000297.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000298.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000299.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerImpl.src/M000300.html +18 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerWrapper.html +210 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerWrapper.src/M000291.html +20 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerWrapper.src/M000292.html +32 -0
- data/doc/rdoc/classes/Ribit/RibitLoggerWrapper.src/M000293.html +18 -0
- data/doc/rdoc/classes/Ribit/Writer.html +163 -0
- data/doc/rdoc/classes/Ribit/Writer.src/M000302.html +18 -0
- data/doc/rdoc/classes/Ribit/Writer.src/M000303.html +21 -0
- data/doc/rdoc/classes/RibitConfig.html +247 -0
- data/doc/rdoc/classes/RibitConfig.src/M000072.html +32 -0
- data/doc/rdoc/classes/RibitConfig.src/M000073.html +18 -0
- data/doc/rdoc/classes/RibitConfig.src/M000074.html +18 -0
- data/doc/rdoc/classes/RibitConfig.src/M000075.html +18 -0
- data/doc/rdoc/classes/RibitConfigParser.html +140 -0
- data/doc/rdoc/classes/RibitConfigParser.src/M000117.html +45 -0
- data/doc/rdoc/classes/RibitData.html +128 -0
- data/doc/rdoc/classes/RibitData/CategoriesWriter.html +169 -0
- data/doc/rdoc/classes/RibitData/CategoriesWriter.src/M000338.html +18 -0
- data/doc/rdoc/classes/RibitData/CategoriesWriter.src/M000339.html +27 -0
- data/doc/rdoc/classes/RibitData/CategoriesWriter.src/M000340.html +24 -0
- data/doc/rdoc/classes/RibitData/Category.html +485 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000313.html +27 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000314.html +36 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000315.html +22 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000316.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000317.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000318.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000319.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000320.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000321.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000322.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000323.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000324.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000325.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000326.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000327.html +36 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000328.html +18 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000329.html +48 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000330.html +45 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000331.html +30 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000332.html +25 -0
- data/doc/rdoc/classes/RibitData/Category.src/M000333.html +18 -0
- data/doc/rdoc/classes/RibitData/CategoryParser.html +217 -0
- data/doc/rdoc/classes/RibitData/CategoryParser.src/M000357.html +18 -0
- data/doc/rdoc/classes/RibitData/CategoryParser.src/M000358.html +29 -0
- data/doc/rdoc/classes/RibitData/CategoryParser.src/M000359.html +31 -0
- data/doc/rdoc/classes/RibitData/CategoryParser.src/M000360.html +27 -0
- data/doc/rdoc/classes/RibitData/CategoryParser.src/M000361.html +45 -0
- data/doc/rdoc/classes/RibitData/Page.html +313 -0
- data/doc/rdoc/classes/RibitData/Page.src/M000362.html +33 -0
- data/doc/rdoc/classes/RibitData/Page.src/M000363.html +22 -0
- data/doc/rdoc/classes/RibitData/Page.src/M000364.html +18 -0
- data/doc/rdoc/classes/RibitData/Page.src/M000365.html +18 -0
- data/doc/rdoc/classes/RibitData/Page.src/M000366.html +18 -0
- data/doc/rdoc/classes/RibitData/Page.src/M000367.html +46 -0
- data/doc/rdoc/classes/RibitData/Page.src/M000368.html +26 -0
- data/doc/rdoc/classes/RibitData/PageParser.html +190 -0
- data/doc/rdoc/classes/RibitData/PageParser.src/M000334.html +19 -0
- data/doc/rdoc/classes/RibitData/PageParser.src/M000335.html +32 -0
- data/doc/rdoc/classes/RibitData/PageParser.src/M000336.html +42 -0
- data/doc/rdoc/classes/RibitData/PageParser.src/M000337.html +21 -0
- data/doc/rdoc/classes/RibitData/RibitData.html +389 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000341.html +26 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000342.html +22 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000343.html +18 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000344.html +36 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000345.html +18 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000346.html +25 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000347.html +18 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000348.html +22 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000349.html +18 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000350.html +30 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000351.html +18 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000352.html +48 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000353.html +30 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000354.html +22 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000355.html +22 -0
- data/doc/rdoc/classes/RibitData/RibitData.src/M000356.html +22 -0
- data/doc/rdoc/classes/RibitData/RibitDataException.html +113 -0
- data/doc/rdoc/classes/RibitException.html +117 -0
- data/doc/rdoc/classes/RibitLinkContainer.html +156 -0
- data/doc/rdoc/classes/RibitLinkContainer.src/M000211.html +85 -0
- data/doc/rdoc/classes/RibitLinkContainer.src/M000212.html +18 -0
- data/doc/rdoc/classes/RibitLinkParser.html +137 -0
- data/doc/rdoc/classes/RibitLinkParser.src/M000100.html +50 -0
- data/doc/rdoc/classes/RibitServlet.html +196 -0
- data/doc/rdoc/classes/RibitServlet.src/M000222.html +37 -0
- data/doc/rdoc/classes/RibitServlet.src/M000223.html +53 -0
- data/doc/rdoc/classes/RibitServlet.src/M000224.html +39 -0
- data/doc/rdoc/classes/RibitServlet.src/M000225.html +19 -0
- data/doc/rdoc/classes/RootContainer.html +139 -0
- data/doc/rdoc/classes/RootContainer.src/M000206.html +19 -0
- data/doc/rdoc/classes/SaveAction.html +164 -0
- data/doc/rdoc/classes/SaveAction.src/M000162.html +24 -0
- data/doc/rdoc/classes/SaveAction.src/M000163.html +116 -0
- data/doc/rdoc/classes/SaveCategoryAction.html +164 -0
- data/doc/rdoc/classes/SaveCategoryAction.src/M000047.html +24 -0
- data/doc/rdoc/classes/SaveCategoryAction.src/M000048.html +97 -0
- data/doc/rdoc/classes/SectionContainer.html +156 -0
- data/doc/rdoc/classes/SectionContainer.src/M000070.html +19 -0
- data/doc/rdoc/classes/SectionContainer.src/M000071.html +20 -0
- data/doc/rdoc/classes/SectionParser.html +137 -0
- data/doc/rdoc/classes/SectionParser.src/M000152.html +41 -0
- data/doc/rdoc/classes/SelectOptionTag.html +177 -0
- data/doc/rdoc/classes/SelectOptionTag.src/M000156.html +22 -0
- data/doc/rdoc/classes/SelectOptionTag.src/M000157.html +18 -0
- data/doc/rdoc/classes/StyleSheetAction.html +182 -0
- data/doc/rdoc/classes/StyleSheetAction.src/M000226.html +31 -0
- data/doc/rdoc/classes/StyleSheetAction.src/M000227.html +36 -0
- data/doc/rdoc/classes/TextContainer.html +214 -0
- data/doc/rdoc/classes/TextContainer.src/M000050.html +19 -0
- data/doc/rdoc/classes/TextContainer.src/M000051.html +18 -0
- data/doc/rdoc/classes/TextContainer.src/M000052.html +18 -0
- data/doc/rdoc/classes/TextContainer.src/M000053.html +18 -0
- data/doc/rdoc/classes/TextContainer.src/M000054.html +18 -0
- data/doc/rdoc/classes/TextContainer.src/M000055.html +18 -0
- data/doc/rdoc/classes/TextPage.html +226 -0
- data/doc/rdoc/classes/TextPage.src/M000198.html +29 -0
- data/doc/rdoc/classes/TextPage.src/M000199.html +18 -0
- data/doc/rdoc/classes/TextPage.src/M000200.html +54 -0
- data/doc/rdoc/classes/TextPage.src/M000201.html +36 -0
- data/doc/rdoc/classes/TextPage.src/M000202.html +46 -0
- data/doc/rdoc/classes/TextPage.src/M000203.html +25 -0
- data/doc/rdoc/classes/URL.html +182 -0
- data/doc/rdoc/classes/URL.src/M000123.html +24 -0
- data/doc/rdoc/classes/URL.src/M000124.html +19 -0
- data/doc/rdoc/classes/URL.src/M000125.html +35 -0
- data/doc/rdoc/classes/UnformattedContentContainer.html +156 -0
- data/doc/rdoc/classes/UnformattedContentContainer.src/M000079.html +20 -0
- data/doc/rdoc/classes/UnformattedContentContainer.src/M000080.html +20 -0
- data/doc/rdoc/classes/UnformattedContentParser.html +137 -0
- data/doc/rdoc/classes/UnformattedContentParser.src/M000194.html +49 -0
- data/doc/rdoc/classes/ViewAction.html +221 -0
- data/doc/rdoc/classes/ViewAction.src/M000009.html +25 -0
- data/doc/rdoc/classes/ViewAction.src/M000010.html +20 -0
- data/doc/rdoc/classes/ViewAction.src/M000011.html +77 -0
- data/doc/rdoc/classes/ViewAction.src/M000012.html +18 -0
- data/doc/rdoc/classes/ViewAction.src/M000013.html +22 -0
- data/doc/rdoc/classes/ViewActionAdapter.html +186 -0
- data/doc/rdoc/classes/ViewActionAdapter.src/M000022.html +20 -0
- data/doc/rdoc/classes/ViewActionAdapter.src/M000023.html +24 -0
- data/doc/rdoc/classes/ViewActionAdapter.src/M000024.html +20 -0
- data/doc/rdoc/classes/ViewActionAdapter.src/M000025.html +21 -0
- data/doc/rdoc/classes/ViewCategoriesAction.html +211 -0
- data/doc/rdoc/classes/ViewCategoriesAction.src/M000261.html +25 -0
- data/doc/rdoc/classes/ViewCategoriesAction.src/M000262.html +20 -0
- data/doc/rdoc/classes/ViewCategoriesAction.src/M000263.html +61 -0
- data/doc/rdoc/classes/ViewCategoriesAction.src/M000264.html +22 -0
- data/doc/rdoc/classes/ViewCategoriesActionAdapter.html +171 -0
- data/doc/rdoc/classes/ViewCategoriesActionAdapter.src/M000089.html +18 -0
- data/doc/rdoc/classes/ViewCategoriesActionAdapter.src/M000090.html +24 -0
- data/doc/rdoc/classes/ViewCategoriesActionAdapter.src/M000091.html +18 -0
- data/doc/rdoc/classes/W3CValidatorLinkActionAdapter.html +156 -0
- data/doc/rdoc/classes/W3CValidatorLinkActionAdapter.src/M000110.html +26 -0
- data/doc/rdoc/classes/W3CValidatorLinkActionAdapter.src/M000111.html +18 -0
- data/doc/rdoc/classes/WebAction.html +165 -0
- data/doc/rdoc/classes/WebAction.src/M000242.html +18 -0
- data/doc/rdoc/classes/WebAction.src/M000243.html +19 -0
- data/doc/rdoc/classes/WebPage.html +184 -0
- data/doc/rdoc/classes/WebPage.src/M000170.html +17 -0
- data/doc/rdoc/classes/WebPage.src/M000171.html +19 -0
- data/doc/rdoc/classes/WebPage.src/M000172.html +18 -0
- data/doc/rdoc/classes/WebPage.src/M000173.html +18 -0
- data/doc/rdoc/classes/XHTMLDocument.html +377 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000136.html +26 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000137.html +40 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000138.html +20 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000139.html +18 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000140.html +18 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000141.html +19 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000142.html +21 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000143.html +30 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000144.html +18 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000145.html +18 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000146.html +23 -0
- data/doc/rdoc/classes/XHTMLDocument.src/M000147.html +18 -0
- data/doc/rdoc/classes/XHTMLException.html +117 -0
- data/doc/rdoc/classes/XHTMLPage.html +225 -0
- data/doc/rdoc/classes/XHTMLPage.src/M000188.html +20 -0
- data/doc/rdoc/classes/XHTMLPage.src/M000189.html +18 -0
- data/doc/rdoc/classes/XHTMLPage.src/M000190.html +44 -0
- data/doc/rdoc/classes/XHTMLPage.src/M000191.html +18 -0
- data/doc/rdoc/classes/XHTMLPage.src/M000192.html +54 -0
- data/doc/rdoc/classes/XHTMLPage.src/M000193.html +22 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/CHANGES.html +150 -0
- data/doc/rdoc/files/INSTALL.html +169 -0
- data/doc/rdoc/files/LICENSE.html +449 -0
- data/doc/rdoc/files/README.html +176 -0
- data/doc/rdoc/files/lib/common/assert_rb.html +101 -0
- data/doc/rdoc/files/lib/common/cvs_rb.html +116 -0
- data/doc/rdoc/files/lib/common/datastorage_rb.html +108 -0
- data/doc/rdoc/files/lib/common/loggerfactory_rb.html +108 -0
- data/doc/rdoc/files/lib/common/pid_rb.html +101 -0
- data/doc/rdoc/files/lib/common/properties_rb.html +101 -0
- data/doc/rdoc/files/lib/common/url_rb.html +108 -0
- data/doc/rdoc/files/lib/log4r/outputter/extendedrollingfileoutputter_rb.html +111 -0
- data/doc/rdoc/files/lib/ribit/action_rb.html +116 -0
- data/doc/rdoc/files/lib/ribit/actionelement_rb.html +108 -0
- data/doc/rdoc/files/lib/ribit/common_rb.html +130 -0
- data/doc/rdoc/files/lib/ribit/common_rb.src/M000001.html +25 -0
- data/doc/rdoc/files/lib/ribit/config_rb.html +116 -0
- data/doc/rdoc/files/lib/ribit/constants_rb.html +101 -0
- data/doc/rdoc/files/lib/ribit/contentparser_rb.html +112 -0
- data/doc/rdoc/files/lib/ribit/contentstore_rb.html +112 -0
- data/doc/rdoc/files/lib/ribit/localization_rb.html +108 -0
- data/doc/rdoc/files/lib/ribit/main_rb.html +120 -0
- data/doc/rdoc/files/lib/ribit/ribit_rb.html +123 -0
- data/doc/rdoc/files/lib/ribit/ribitdata_rb.html +112 -0
- data/doc/rdoc/files/lib/ribit/ribitlogger_rb.html +111 -0
- data/doc/rdoc/files/lib/ribit/webpage_rb.html +118 -0
- data/doc/rdoc/files/lib/ribit/xhtmldocument_rb.html +109 -0
- data/doc/rdoc/files/lib/ribit/xhtmltag_rb.html +109 -0
- data/doc/rdoc/fr_class_index.html +150 -0
- data/doc/rdoc/fr_file_index.html +53 -0
- data/doc/rdoc/fr_method_index.html +411 -0
- data/doc/rdoc/index.html +24 -0
- data/doc/rdoc/rdoc-style.css +208 -0
- data/doc/spec.txt +42 -0
- data/doc/test_run_25052005.txt +108 -0
- data/doc/testplan.txt +87 -0
- data/doc/www/index.html +5 -0
- data/lib/common/assert.rb +72 -0
- data/lib/common/cvs.rb +201 -0
- data/lib/common/datastorage.rb +265 -0
- data/lib/common/loggerfactory.rb +56 -0
- data/lib/common/pid.rb +44 -0
- data/lib/common/properties.rb +89 -0
- data/lib/common/url.rb +64 -0
- data/lib/log4r/outputter/extendedrollingfileoutputter.rb +73 -0
- data/lib/ribit/action.rb +1106 -0
- data/lib/ribit/actionelement.rb +152 -0
- data/lib/ribit/common.rb +34 -0
- data/lib/ribit/config.rb +123 -0
- data/lib/ribit/constants.rb +50 -0
- data/lib/ribit/contentparser.rb +1111 -0
- data/lib/ribit/contentstore.rb +406 -0
- data/lib/ribit/localization.rb +76 -0
- data/lib/ribit/main.rb +114 -0
- data/lib/ribit/ribit.rb +319 -0
- data/lib/ribit/ribitdata.rb +909 -0
- data/lib/ribit/ribitlogger.rb +192 -0
- data/lib/ribit/webpage.rb +802 -0
- data/lib/ribit/xhtmldocument.rb +148 -0
- data/lib/ribit/xhtmltag.rb +189 -0
- data/share/config/content/1/1.xml +6 -0
- data/share/config/content/1/2.xml +6 -0
- data/share/config/content/1/3.xml +6 -0
- data/share/config/content/1/4.xml +6 -0
- data/share/config/content/1/5.xml +6 -0
- data/share/config/content/1/category.xml +7 -0
- data/share/config/content/1/files/edit-category-template.html +59 -0
- data/share/config/content/1/files/edit-template.html +88 -0
- data/share/config/content/1/files/localization_en.properties +11 -0
- data/share/config/content/1/files/ribit.css +215 -0
- data/share/config/content/1/files/view-template.html +50 -0
- data/share/config/content/2/1.xml +19 -0
- data/share/config/content/2/2.xml +54 -0
- data/share/config/content/2/category.xml +5 -0
- data/share/config/content/3/1.xml +11 -0
- data/share/config/content/3/3.xml +17 -0
- data/share/config/content/3/4.xml +28 -0
- data/share/config/content/3/category.xml +5 -0
- data/share/config/content/categories.xml +12 -0
- data/share/config/ribitconfig.xml +48 -0
- data/share/config/ribitconfig_dev.xml +41 -0
- data/share/config/ribitconfig_local.xml +39 -0
- data/share/test/config/content/1/1.xml +6 -0
- data/share/test/config/content/1/2.xml +6 -0
- data/share/test/config/content/1/3.xml +6 -0
- data/share/test/config/content/1/4.xml +6 -0
- data/share/test/config/content/1/category.xml +4 -0
- data/share/test/config/content/1/files/edit-template.html +50 -0
- data/share/test/config/content/1/files/localization_en.properties +4 -0
- data/share/test/config/content/1/files/ribit.css +139 -0
- data/share/test/config/content/1/files/view-template.html +36 -0
- data/share/test/config/content/2/1.xml +16 -0
- data/share/test/config/content/2/2.xml +25 -0
- data/share/test/config/content/2/category.xml +4 -0
- data/share/test/config/content/categories.xml +11 -0
- data/share/test/config/content/ribitdata.xml +348 -0
- data/share/test/config/ribitconfig.xml +36 -0
- data/share/test/test1.xml +13 -0
- data/share/test/test2.xml +17 -0
- data/share/test/test3.xml +5 -0
- data/test/alltests.rb +35 -0
- data/test/common/allcommontests.rb +40 -0
- data/test/common/asserttest.rb +71 -0
- data/test/common/cvstest.rb +117 -0
- data/test/common/datastoragetest.rb +151 -0
- data/test/common/filepersistentstoragehandlertest.rb +105 -0
- data/test/common/propertiestest.rb +77 -0
- data/test/common/urltest.rb +70 -0
- data/test/log4r/outputter/alllog4routputtertests.rb +28 -0
- data/test/log4r/outputter/extendedrollingfileoutputtertest.rb +77 -0
- data/test/mock/mock.rb +147 -0
- data/test/ribit/actionadaptertest.rb +58 -0
- data/test/ribit/actionelementtest.rb +147 -0
- data/test/ribit/actionmanagertest.rb +55 -0
- data/test/ribit/allribittests.rb +62 -0
- data/test/ribit/categoryformactiontest.rb +153 -0
- data/test/ribit/configtest.rb +43 -0
- data/test/ribit/contentparsertest.rb +404 -0
- data/test/ribit/contentstorestub.rb +64 -0
- data/test/ribit/contentstoretest.rb +222 -0
- data/test/ribit/editcategorypagetest.rb +121 -0
- data/test/ribit/formactiontest.rb +367 -0
- data/test/ribit/localizationtest.rb +65 -0
- data/test/ribit/loggertest.rb +44 -0
- data/test/ribit/misc/allmisctests.rb +32 -0
- data/test/ribit/misc/amritatest.rb +24 -0
- data/test/ribit/misc/debugservlet.rb +63 -0
- data/test/ribit/misc/postsevlet.rb +36 -0
- data/test/ribit/misc/rexmlcdatatest.rb +17 -0
- data/test/ribit/misc/rexmldoctypetest.rb +20 -0
- data/test/ribit/misc/rexmlreadtest.rb +13 -0
- data/test/ribit/misc/rexmlwritetest.rb +28 -0
- data/test/ribit/misc/rubytest.rb +184 -0
- data/test/ribit/misc/suidtest.rb +21 -0
- data/test/ribit/misc/suite.rb +12 -0
- data/test/ribit/misc/wwwtest.rb +68 -0
- data/test/ribit/pagerequesttest.rb +74 -0
- data/test/ribit/ribitdatatest.rb +404 -0
- data/test/ribit/ribitservlettest.rb +94 -0
- data/test/ribit/testdata/ribittestdata.rb +49 -0
- data/test/ribit/testutil/ribitstub.rb +83 -0
- data/test/ribit/testutil/ribittestcase.rb +66 -0
- data/test/ribit/viewactiontest.rb +332 -0
- data/test/ribit/webpagetest.rb +531 -0
- data/test/ribit/xhtmldocumenttest.rb +263 -0
- data/test/ribit/xhtmltagtest.rb +84 -0
- metadata +837 -0
data/lib/ribit/main.rb
ADDED
|
@@ -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
|
+
|
data/lib/ribit/ribit.rb
ADDED
|
@@ -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
|