kodekopelli 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/CHANGELOG +3 -0
  2. data/LICENSE +32 -0
  3. data/README +78 -0
  4. data/Rakefile +87 -0
  5. data/bin/kodekopelli +5 -0
  6. data/examples/faqomatic/config.xml +40 -0
  7. data/examples/faqomatic/content.rhtml +376 -0
  8. data/examples/faqomatic/generated/README.txt +1 -0
  9. data/examples/faqomatic/includes/shampoo_answer.txt +1 -0
  10. data/examples/faqomatic/templates/faqs.txt +22 -0
  11. data/examples/faqomatic/templates/great_big.txt +3 -0
  12. data/examples/faqomatic/templates/html_wrapper.txt +9 -0
  13. data/examples/thankyounotes/config.xml +18 -0
  14. data/examples/thankyounotes/content.rhtml +528 -0
  15. data/examples/thankyounotes/generated/README.txt +1 -0
  16. data/examples/thankyounotes/includes/poem.txt +3 -0
  17. data/examples/thankyounotes/templates/thanks.txt +14 -0
  18. data/examples/treemenu/config.xml +110 -0
  19. data/examples/treemenu/content.rhtml +324 -0
  20. data/examples/treemenu/generated/README.txt +1 -0
  21. data/examples/treemenu/templates/authorized.txt +1 -0
  22. data/examples/treemenu/templates/menu_category.txt +4 -0
  23. data/examples/treemenu/templates/menu_item.txt +3 -0
  24. data/examples/treemenu/templates/simple_menu.txt +3 -0
  25. data/lib/kodekopelli.rb +56 -0
  26. data/lib/kodekopelli/expandable_properties.rb +63 -0
  27. data/lib/kodekopelli/file_generator.rb +726 -0
  28. data/lib/kodekopelli/frozen_key_hash.rb +67 -0
  29. data/lib/kodekopelli/minimal_logger.rb +50 -0
  30. data/lib/kodekopelli/properties_file.rb +41 -0
  31. data/lib/kodekopelli/util.rb +30 -0
  32. data/rakefile +87 -0
  33. data/test/abstract_unit.rb +4 -0
  34. data/test/fixtures/definitions/invalid/empty +0 -0
  35. data/test/fixtures/definitions/invalid/gibberish.txt +6 -0
  36. data/test/fixtures/definitions/kodekopelli.xsd +95 -0
  37. data/test/fixtures/definitions/valid/empty_files.xml +49 -0
  38. data/test/fixtures/definitions/valid/kodekopelli_rocks_files.xml +359 -0
  39. data/test/fixtures/definitions/valid/simplest.xml +8 -0
  40. data/test/fixtures/includes/bang.txt +1 -0
  41. data/test/fixtures/includes/c.txt +1 -0
  42. data/test/fixtures/includes/d.txt +1 -0
  43. data/test/fixtures/includes/e.txt +1 -0
  44. data/test/fixtures/includes/empty.txt +0 -0
  45. data/test/fixtures/includes/i.txt +1 -0
  46. data/test/fixtures/includes/k.txt +1 -0
  47. data/test/fixtures/includes/k_upper.txt +1 -0
  48. data/test/fixtures/includes/kodekopelli_rocks.txt +1 -0
  49. data/test/fixtures/includes/l.txt +1 -0
  50. data/test/fixtures/includes/o.txt +1 -0
  51. data/test/fixtures/includes/p.txt +1 -0
  52. data/test/fixtures/includes/r.txt +1 -0
  53. data/test/fixtures/includes/s.txt +1 -0
  54. data/test/fixtures/includes/space.txt +1 -0
  55. data/test/fixtures/properties/comments.properties +17 -0
  56. data/test/fixtures/properties/empty.properties +0 -0
  57. data/test/fixtures/properties/expandable.properties +2 -0
  58. data/test/fixtures/properties/none_valid.properties +1 -0
  59. data/test/fixtures/properties/simple.properties +5 -0
  60. data/test/fixtures/templates/anything_att.txt +1 -0
  61. data/test/fixtures/templates/anything_att_prop.txt +1 -0
  62. data/test/fixtures/templates/anything_prop.txt +1 -0
  63. data/test/fixtures/templates/anything_prop_att.txt +1 -0
  64. data/test/fixtures/templates/blank.txt +0 -0
  65. data/test/fixtures/templates/child_output.txt +1 -0
  66. data/test/fixtures/templates/kodekopelli_blanks +1 -0
  67. data/test/tc_expandable_properties.rb +106 -0
  68. data/test/tc_file_generator.rb +20 -0
  69. data/test/tc_frozen_key_hash.rb +34 -0
  70. data/test/tc_properties_file.rb +52 -0
  71. data/test/tc_util.rb +55 -0
  72. data/test/ts_all_tests.rb +9 -0
  73. data/test/ts_functional.rb +86 -0
  74. metadata +133 -0
@@ -0,0 +1 @@
1
+ This folder contains all content generated by Kodekopelli processing.
@@ -0,0 +1,3 @@
1
+ Roses are red,
2
+ Violets are blue,
3
+ That was awfully nice of you!
@@ -0,0 +1,14 @@
1
+ <%= include_file(att('poem')) %>
2
+
3
+ <%= Time.now.strftime("%B %d, %Y") %>
4
+
5
+ Dear <%= att('to', 'Friend') %>,
6
+
7
+ Thank-you very much for <%= att('purpose', 'everything') %>.
8
+
9
+ <%= att('closing', 'Yours Truly') %>,
10
+
11
+ <%= att('from', 'Kodekopelli') %>
12
+ <% unless att('ps',nil).nil? %>
13
+ P.S. <%= att('ps') %>
14
+ <% end %>
@@ -0,0 +1,110 @@
1
+ <kodekopelli
2
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xsi:noNamespaceSchemaLocation="http://www.kodekopelli.org/xml/schemas/kodekopelli.xsd">
4
+ <!-- Project structure properties. These locations should
5
+ already exist. -->
6
+ <property location="." name="basedir" />
7
+ <!-- Folder containing Kodekopelli templates. -->
8
+ <property location="${basedir}/templates"
9
+ name="template.dir" />
10
+ <!-- Folder that should contain all Kodekopelli output. -->
11
+ <property location="${basedir}/generated"
12
+ name="output.dir" />
13
+ <!-- Templates -->
14
+ <property location="${template.dir}/simple_menu.txt"
15
+ name="menu" />
16
+ <property location="${template.dir}/menu_category.txt"
17
+ name="category" />
18
+ <property location="${template.dir}/menu_item.txt"
19
+ name="item" />
20
+ <property location="${template.dir}/authorized.txt"
21
+ name="authorized" />
22
+ <!-- URLs -->
23
+ <property name="admin.home.url" value="[URL GOES HERE]" />
24
+ <property name="add.user.url" value="[URL GOES HERE]" />
25
+ <property name="change.user.url" value="[URL GOES HERE]" />
26
+ <property name="delete.user.url" value="[URL GOES HERE]" />
27
+ <property name="admin.sys.url" value="[URL GOES HERE]" />
28
+ <property name="admin.user.url" value="[URL GOES HERE]" />
29
+ <property name="site.statistics.url"
30
+ value="[URL GOES HERE]" />
31
+ <property name="server.status.url" value="[URL GOES HERE]" />
32
+ <property name="auditing.url" value="[URL GOES HERE]" />
33
+ <property name="hr.home.url" value="[URL GOES HERE]" />
34
+ <property name="some.hr.url" value="[URL GOES HERE]" />
35
+ <property name="another.hr.url" value="[URL GOES HERE]" />
36
+ <property name="public.item.one.url"
37
+ value="[URL GOES HERE]" />
38
+ <property name="public.item.two.url"
39
+ value="[URL GOES HERE]" />
40
+ <property name="marketing.home.url"
41
+ value="[URL GOES HERE]" />
42
+ <property name="some.marketing.url"
43
+ value="[URL GOES HERE]" />
44
+ <filegroup>
45
+ <!-- The main menu. -->
46
+ <file name="${output.dir}/main_menu.jsp">
47
+ <composite template="${menu}">
48
+ <composite template="${category}"
49
+ text="Public Menu Category">
50
+ <composite template="${menu}">
51
+ <template target="_blank" template="${item}" text="Public Item One"
52
+ url="${public.item.one.url}" />
53
+ <template template="${item}" text="Public Item Two"
54
+ url="${public.item.two.url}" />
55
+ </composite>
56
+ </composite>
57
+ <composite roles="ROLE_MARKETING"
58
+ template="${authorized}">
59
+ <composite target="_blank" template="${category}"
60
+ text="Marketing Menu Category"
61
+ url="${marketing.home.url}">
62
+ <composite template="${menu}">
63
+ <template template="${item}" text="Marketing Item One" url="${some.marketing.url}" />
64
+ </composite>
65
+ </composite>
66
+ </composite>
67
+ <composite roles="ROLE_HUMAN_RESOURCES"
68
+ template="${authorized}">
69
+ <composite target="_blank" template="${category}"
70
+ text="Human Resources Menu Category"
71
+ url="${hr.home.url}">
72
+ <composite template="${menu}">
73
+ <template template="${item}" text="HR Item One" url="${some.hr.url}" />
74
+ <template template="${item}" text="HR Item Two" url="${another.hr.url}" />
75
+ </composite>
76
+ </composite>
77
+ </composite>
78
+ <composite roles="ROLE_SYS_ADMIN"
79
+ template="${authorized}">
80
+ <composite target="_blank" template="${category}"
81
+ text="Amin Menu Category"
82
+ url="${admin.home.url}">
83
+ <composite template="${menu}">
84
+ <composite target="_blank"
85
+ template="${category}"
86
+ text="User Administration Menu Category"
87
+ url="${admin.user.url}">
88
+ <composite template="${menu}">
89
+ <template template="${item}" text="Add User" url="${add.user.url}" />
90
+ <template template="${item}" text="Change User" url="${change.user.url}" />
91
+ <template template="${item}" text="Delete User" url="${delete.user.url}" />
92
+ </composite>
93
+ </composite>
94
+ <composite target="_blank"
95
+ template="${category}"
96
+ text="System Administration Menu Category"
97
+ url="${admin.sys.url}">
98
+ <composite template="${menu}">
99
+ <template template="${item}" text="Auditing" url="${auditing.url}" />
100
+ <template template="${item}" text="Site Statistics" url="${site.statistics.url}" />
101
+ <template template="${item}" text="Server Status" url="${server.status.url}" />
102
+ </composite>
103
+ </composite>
104
+ </composite>
105
+ </composite>
106
+ </composite>
107
+ </composite>
108
+ </file>
109
+ </filegroup>
110
+ </kodekopelli>
@@ -0,0 +1,324 @@
1
+ <p class="note">
2
+ <strong>Please Note</strong> This example should be considered a work in progress.
3
+ Although all associated configuration files and templates have been completed and
4
+ are included in this example, not all supporting text has been added.
5
+ </p>
6
+ <p>
7
+ This simple example demonstrates basic Kodekopelli functionality
8
+ and recommended practices. The following Kodekopelli concepts
9
+ not covered by previous examples are illustrated herein:
10
+ </p>
11
+ <ul>
12
+ <li>
13
+ Integrating other view layer technologies
14
+ (JSP custom tags) in Kodekopelli templates.
15
+ </li>
16
+ <li>
17
+ Nesting <a href="<%= att 'manual' %>#composites">composite</a>
18
+ elements in Kodekopelli configuration files.
19
+ </li>
20
+ </ul>
21
+ <p>
22
+ Unlike the introductory examples (<a href="/examples/thankyounotes">Thank-You Notes</a>
23
+ and <a href="/examples/faqomatic">FAQ-O-Matic</a>),
24
+ this example doesn't strive to impart deep knowledge of the Kodekopelli
25
+ directives used herein; rather, it presents those templates and configuration
26
+ files necessary to achieve the goal state shown below.
27
+ </p>
28
+ <h2>Problem</h2>
29
+ <p>
30
+ Several sites on your corporate intranet make use of complex tree menus.
31
+ Each menu is composed of one (1) or more top level menu categories and
32
+ each menu category is composed of one (1) or more menu items or additional
33
+ categories. Further, the menus often must nest to three (3) or four (4)
34
+ levels deep. To complicate things even more, each menu category and menu item
35
+ may need to be wrapped, individually, with one or more JSP custom tags that provide
36
+ access control, among other things. When combined with significant CSS
37
+ directives, your menu-related JSPs have become unwieldy and prone to human
38
+ error.
39
+ </p>
40
+ <h2>Solution</h2>
41
+ <p>
42
+ Use Kodekopelli as an additional layer of abstraction for
43
+ generating tree menu JSP fragments. The relevant menu-related
44
+ entries in the Kodekopelli configuration file(s) will then
45
+ serve as a kind of
46
+ <a href="http://en.wikipedia.org/wiki/Domain_Specific_Language"
47
+ target="">domain-specific language</a> that is easily
48
+ modifiable by humans, leaving the tedious process of JSP construction
49
+ to Kodekopelli.
50
+ </p>
51
+ <h3>Project Structure</h3>
52
+ <p>
53
+ As with the previous examples, those files that Kodekopelli
54
+ <em>generates</em> will be separated from those
55
+ that he uses to generate said files. Starting from a fresh, empty folder
56
+ of your choice, create subfolders mirroring the following structure:
57
+ </p>
58
+ <pre class="code">
59
+ /generated
60
+ /templates
61
+ </pre>
62
+ <h3>The Goal</h3>
63
+ <ul>
64
+ <li>
65
+ Public Menu Category
66
+ <br />
67
+ <ul>
68
+ <li>
69
+ <a href="" target="">
70
+ Public Item One
71
+ </a>
72
+ </li>
73
+ <li>
74
+ <a href="" target="">
75
+ Public Item Two
76
+ </a>
77
+ </li>
78
+ </ul>
79
+ </li>
80
+ <li>
81
+ <a href="" target="">
82
+ Marketing Menu Category
83
+ </a>
84
+ <br />
85
+ <ul>
86
+ <li>
87
+ <a href="" target="">
88
+ Marketing Item One
89
+ </a>
90
+ </li>
91
+ </ul>
92
+ </li>
93
+ <li>
94
+ <a href="" target="">
95
+ Human Resources Menu Category
96
+ </a>
97
+ <br />
98
+ <ul>
99
+ <li>
100
+ <a href="" target="">
101
+ HR Item One
102
+ </a>
103
+ </li>
104
+ <li>
105
+ <a href="" target="">
106
+ HR Item Two
107
+ </a>
108
+ </li>
109
+ </ul>
110
+ </li>
111
+ <li>
112
+ <a href="" target="">
113
+ Amin Menu Category
114
+ </a>
115
+ <br />
116
+ <ul>
117
+ <li>
118
+ <a href="" target="">
119
+ User Administration Menu Category
120
+ </a>
121
+ <br />
122
+ <ul>
123
+ <li>
124
+ <a href="" target="">
125
+ Add User
126
+ </a>
127
+ </li>
128
+ <li>
129
+ <a href="" target="">
130
+ Change User
131
+ </a>
132
+ </li>
133
+ <li>
134
+ <a href="" target="">
135
+ Delete User
136
+ </a>
137
+ </li>
138
+ </ul>
139
+ </li>
140
+ <li>
141
+ <a href="" target="">
142
+ System Administration Menu Category
143
+ </a>
144
+ <br />
145
+ <ul>
146
+ <li>
147
+ <a href="" target="">
148
+ Auditing
149
+ </a>
150
+ </li>
151
+ <li>
152
+ <a href="" target="">
153
+ Site Statistics
154
+ </a>
155
+ </li>
156
+ <li>
157
+ <a href="" target="">
158
+ Server Status
159
+ </a>
160
+ </li>
161
+ </ul>
162
+ </li>
163
+ </ul>
164
+ </li>
165
+ </ul>
166
+ <h3>Templates</h3>
167
+ <p>
168
+ The menu shown above may be created using four simple templates, described
169
+ below.
170
+ </p>
171
+ <h4>Simple Menu Template</h4>
172
+ <pre class="code">
173
+ &lt;ul&gt;&lt;% child_iterator { |current_child, text| %&gt;
174
+ &lt;%= text %&gt;&lt;% } %&gt;
175
+ &lt;/ul&gt;
176
+ </pre>
177
+ <h4>Menu Category Template</h4>
178
+ <pre class="code">
179
+ &lt;li&gt;&lt;% unless att('url',nil).nil? %&gt;&lt;a href="&lt;%= att('url') %&gt;"
180
+ target="&lt;%= att('target') %&gt;"
181
+ &gt;&lt;% end %&gt;&lt;%= h att('text') %&gt;&lt;% unless att('url',nil).nil? %&gt;&lt;/a&gt;&lt;% end %&gt;&lt;br /&gt;
182
+ &lt;%= child_output %&gt;&lt;/li&gt;
183
+ </pre>
184
+ <h4>Menu Item Template</h4>
185
+ <pre class="code">
186
+ &lt;li&gt;&lt;% unless att('url',nil).nil? %&gt;&lt;a href="&lt;%= att('url') %&gt;"
187
+ target="&lt;%= att('target') %&gt;"
188
+ &gt;&lt;% end %&gt;&lt;%= h att('text') %&gt;&lt;% unless att('url',nil).nil? %&gt;&lt;/a&gt;&lt;% end %&gt;&lt;/li&gt;
189
+ </pre>
190
+ <h4>Authorization Control Template</h4>
191
+ <p>
192
+ This template leverages the <em>authz</em> JSP custom tag library provided by
193
+ the open source <a href="http://acegisecurity.sourceforge.net/"
194
+ target="_blank">Acegi Security System</a>.
195
+ </p>
196
+ <pre class="code">
197
+ &lt;authz:authorize ifAnyGranted="&lt;%= att('roles') %&gt;"&gt;&lt;%= child_output %&gt;&lt;/authz:authorize&gt;
198
+ </pre>
199
+ <h3>Configuration File</h3>
200
+ <p>
201
+ The completed Kodekopelli configuration file is shown, in its entirety,
202
+ below.
203
+ </p>
204
+ <pre class="code">
205
+ &lt;kodekopelli&gt;
206
+ &lt;!-- Project structure properties. These locations should
207
+ already exist. --&gt;
208
+ &lt;property location="." name="basedir" /&gt;
209
+ &lt;!-- Folder containing Kodekopelli templates. --&gt;
210
+ &lt;property location="${basedir}/templates"
211
+ name="template.dir" /&gt;
212
+ &lt;!-- Folder that should contain all Kodekopelli output. --&gt;
213
+ &lt;property location="${basedir}/generated"
214
+ name="output.dir" /&gt;
215
+ &lt;!-- Templates --&gt;
216
+ &lt;property location="${template.dir}/simple_menu.txt"
217
+ name="menu" /&gt;
218
+ &lt;property location="${template.dir}/menu_category.txt"
219
+ name="category" /&gt;
220
+ &lt;property location="${template.dir}/menu_item.txt"
221
+ name="item" /&gt;
222
+ &lt;property location="${template.dir}/authorized.txt"
223
+ name="authorized" /&gt;
224
+ &lt;!-- URLs --&gt;
225
+ &lt;property name="admin.home.url" value="[URL GOES HERE]" /&gt;
226
+ &lt;property name="add.user.url" value="[URL GOES HERE]" /&gt;
227
+ &lt;property name="change.user.url" value="[URL GOES HERE]" /&gt;
228
+ &lt;property name="delete.user.url" value="[URL GOES HERE]" /&gt;
229
+ &lt;property name="admin.sys.url" value="[URL GOES HERE]" /&gt;
230
+ &lt;property name="admin.user.url" value="[URL GOES HERE]" /&gt;
231
+ &lt;property name="site.statistics.url"
232
+ value="[URL GOES HERE]" /&gt;
233
+ &lt;property name="server.status.url" value="[URL GOES HERE]" /&gt;
234
+ &lt;property name="auditing.url" value="[URL GOES HERE]" /&gt;
235
+ &lt;property name="hr.home.url" value="[URL GOES HERE]" /&gt;
236
+ &lt;property name="some.hr.url" value="[URL GOES HERE]" /&gt;
237
+ &lt;property name="another.hr.url" value="[URL GOES HERE]" /&gt;
238
+ &lt;property name="public.item.one.url"
239
+ value="[URL GOES HERE]" /&gt;
240
+ &lt;property name="public.item.two.url"
241
+ value="[URL GOES HERE]" /&gt;
242
+ &lt;property name="marketing.home.url"
243
+ value="[URL GOES HERE]" /&gt;
244
+ &lt;property name="some.marketing.url"
245
+ value="[URL GOES HERE]" /&gt;
246
+ &lt;filegroup&gt;
247
+ &lt;!-- The main menu. --&gt;
248
+ &lt;file name="${output.dir}/main_menu.jsp"&gt;
249
+ &lt;composite template="${menu}"&gt;
250
+ &lt;composite template="${category}"
251
+ text="Public Menu Category"&gt;
252
+ &lt;composite template="${menu}"&gt;
253
+ &lt;template target="_blank" template="${item}" text="Public Item One"
254
+ url="${public.item.one.url}" /&gt;
255
+ &lt;template template="${item}" text="Public Item Two"
256
+ url="${public.item.two.url}" /&gt;
257
+ &lt;/composite&gt;
258
+ &lt;/composite&gt;
259
+ &lt;composite roles="ROLE_MARKETING"
260
+ template="${authorized}"&gt;
261
+ &lt;composite target="_blank" template="${category}"
262
+ text="Marketing Menu Category"
263
+ url="${marketing.home.url}"&gt;
264
+ &lt;composite template="${menu}"&gt;
265
+ &lt;template template="${item}" text="Marketing Item One" url="${some.marketing.url}" /&gt;
266
+ &lt;/composite&gt;
267
+ &lt;/composite&gt;
268
+ &lt;/composite&gt;
269
+ &lt;composite roles="ROLE_HUMAN_RESOURCES"
270
+ template="${authorized}"&gt;
271
+ &lt;composite target="_blank" template="${category}"
272
+ text="Human Resources Menu Category"
273
+ url="${hr.home.url}"&gt;
274
+ &lt;composite template="${menu}"&gt;
275
+ &lt;template template="${item}" text="HR Item One" url="${some.hr.url}" /&gt;
276
+ &lt;template template="${item}" text="HR Item Two" url="${another.hr.url}" /&gt;
277
+ &lt;/composite&gt;
278
+ &lt;/composite&gt;
279
+ &lt;/composite&gt;
280
+ &lt;composite roles="ROLE_SYS_ADMIN"
281
+ template="${authorized}"&gt;
282
+ &lt;composite target="_blank" template="${category}"
283
+ text="Amin Menu Category"
284
+ url="${admin.home.url}"&gt;
285
+ &lt;composite template="${menu}"&gt;
286
+ &lt;composite target="_blank"
287
+ template="${category}"
288
+ text="User Administration Menu Category"
289
+ url="${admin.user.url}"&gt;
290
+ &lt;composite template="${menu}"&gt;
291
+ &lt;template template="${item}" text="Add User" url="${add.user.url}" /&gt;
292
+ &lt;template template="${item}" text="Change User" url="${change.user.url}" /&gt;
293
+ &lt;template template="${item}" text="Delete User" url="${delete.user.url}" /&gt;
294
+ &lt;/composite&gt;
295
+ &lt;/composite&gt;
296
+ &lt;composite target="_blank"
297
+ template="${category}"
298
+ text="System Administration Menu Category"
299
+ url="${admin.sys.url}"&gt;
300
+ &lt;composite template="${menu}"&gt;
301
+ &lt;template template="${item}" text="Auditing" url="${auditing.url}" /&gt;
302
+ &lt;template template="${item}" text="Site Statistics" url="${site.statistics.url}" /&gt;
303
+ &lt;template template="${item}" text="Server Status" url="${server.status.url}" /&gt;
304
+ &lt;/composite&gt;
305
+ &lt;/composite&gt;
306
+ &lt;/composite&gt;
307
+ &lt;/composite&gt;
308
+ &lt;/composite&gt;
309
+ &lt;/composite&gt;
310
+ &lt;/file&gt;
311
+ &lt;/filegroup&gt;
312
+ &lt;/kodekopelli&gt;
313
+ </pre>
314
+ <h2>Notes</h2>
315
+ <ul>
316
+ <li>
317
+ It would be very simple to enhance the templates to allow for specifying
318
+ CSS classes for all menu elements, allowing for greater control
319
+ over menu aesthetics. Numerous sites, like
320
+ <a href="http://css.maxdesign.com.au/listamatic/" target="">Listamatic</a>,
321
+ provide great examples for controlling the look and feel (LAF) of
322
+ menus based on unordered lists.
323
+ </li>
324
+ </ul>