Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
AbstractMarkupLanguage |
|
| 1.2916666666666667;1.292 |
1 | /* | |
2 | * $Source$ | |
3 | * $Revision$ | |
4 | * | |
5 | * Copyright (C) 2006 Tim Pizey | |
6 | * | |
7 | * Part of Melati (http://melati.org), a framework for the rapid | |
8 | * development of clean, maintainable web applications. | |
9 | * | |
10 | * Melati is free software; Permission is granted to copy, distribute | |
11 | * and/or modify this software under the terms either: | |
12 | * | |
13 | * a) the GNU General Public License as published by the Free Software | |
14 | * Foundation; either version 2 of the License, or (at your option) | |
15 | * any later version, | |
16 | * | |
17 | * or | |
18 | * | |
19 | * b) any version of the Melati Software License, as published | |
20 | * at http://melati.org | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License and | |
23 | * the Melati Software License along with this program; | |
24 | * if not, write to the Free Software Foundation, Inc., | |
25 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the | |
26 | * GNU General Public License and visit http://melati.org to obtain the | |
27 | * Melati Software License. | |
28 | * | |
29 | * Feel free to contact the Developers of Melati (http://melati.org), | |
30 | * if you would like to work out a different arrangement than the options | |
31 | * outlined here. It is our intention to allow Melati to be used by as | |
32 | * wide an audience as possible. | |
33 | * | |
34 | * This program is distributed in the hope that it will be useful, | |
35 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
36 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
37 | * GNU General Public License for more details. | |
38 | * | |
39 | * Contact details for copyright holder: | |
40 | * | |
41 | * Tim Pizey <timp At paneris.org> | |
42 | * http://paneris.org/~timp | |
43 | */ | |
44 | ||
45 | package org.melati.template; | |
46 | ||
47 | import java.text.DateFormat; | |
48 | ||
49 | import org.melati.Melati; | |
50 | import org.melati.poem.Field; | |
51 | import org.melati.poem.PoemLocale; | |
52 | import org.melati.util.MelatiStringWriter; | |
53 | import org.melati.util.MelatiWriter; | |
54 | ||
55 | /** | |
56 | * MarkupLanguage provides a variety of methods for rendering objects in a | |
57 | * template. | |
58 | * | |
59 | * Each object to be rendered has 3 methods: | |
60 | * 1 - String rendered(Object o) - this will render the object to a String | |
61 | * 2 - void render(Object o) - renders the object to melati.getWriter() | |
62 | * 3 - void render(Object o, MelatiWriter w) - render the object to w. | |
63 | * | |
64 | * When this class was written it was thought that for maximum | |
65 | * efficiency one should render the object direct to the output stream using | |
66 | * method (2) above. | |
67 | * However now all but (1) is deprecated. | |
68 | */ | |
69 | ||
70 | public abstract class AbstractMarkupLanguage implements MarkupLanguage { | |
71 | ||
72 | 968 | protected TempletLoader templetLoader = null; |
73 | 968 | protected Melati melati = null; |
74 | 968 | protected PoemLocale locale = null; |
75 | ||
76 | /** The maximum number of field possibilities to render. */ | |
77 | public static final int FIELD_POSSIBILITIES_LIMIT = 10000; | |
78 | /** The maximum number of date field possibilities to render. */ | |
79 | public static final int DATE_FIELD_POSSIBILITIES_LIMIT = 50; | |
80 | ||
81 | private String name; | |
82 | ||
83 | /** | |
84 | * Construct a Markup Language object. | |
85 | * | |
86 | * @param name - the name associated with this markup language. | |
87 | * This is used to determine where to load | |
88 | * templates from ie 'html' templates are | |
89 | * found in the 'html' directory. | |
90 | * @param melati - the melati currently in use | |
91 | * @param templetLoader - the template loader in use | |
92 | * (taken from org.melati.MelatiConfig.properties) | |
93 | * @param locale - the locale in use | |
94 | * (taken from org.melati.MelatiConfig.properties) | |
95 | */ | |
96 | public AbstractMarkupLanguage(String name, | |
97 | Melati melati, | |
98 | TempletLoader templetLoader, | |
99 | 968 | PoemLocale locale) { |
100 | 968 | this.name = name; |
101 | 968 | this.melati = melati; |
102 | 968 | this.templetLoader = templetLoader; |
103 | 968 | this.locale = locale; |
104 | 968 | } |
105 | ||
106 | /** | |
107 | * Construct a new MarkupLanguage given a new name and an | |
108 | * existing MarkupLanguage. | |
109 | * | |
110 | * @param name - the name of the new MarkupLanguage | |
111 | * @param other - the Markup Language to base this one upon | |
112 | */ | |
113 | protected AbstractMarkupLanguage(String name, AbstractMarkupLanguage other) { | |
114 | 256 | this(name, other.melati, other.templetLoader, other.locale); |
115 | 256 | } |
116 | ||
117 | /** | |
118 | * {@inheritDoc} | |
119 | * @see org.melati.template.MarkupLanguage#getName() | |
120 | */ | |
121 | public String getName() { | |
122 | 1063 | return name; |
123 | } | |
124 | ||
125 | /** | |
126 | * Name and locale. | |
127 | * {@inheritDoc} | |
128 | * @see java.lang.Object#toString() | |
129 | */ | |
130 | public String toString() { | |
131 | 654 | return getName() + "/" + locale.toString(); |
132 | } | |
133 | ||
134 | private MelatiStringWriter getStringWriter() { | |
135 | 8728 | return (MelatiStringWriter)melati.getStringWriter(); |
136 | } | |
137 | ||
138 | /** | |
139 | * {@inheritDoc} | |
140 | * @see org.melati.template.MarkupLanguage#rendered(java.lang.String, int) | |
141 | */ | |
142 | public String rendered(String s, int limit) { | |
143 | 6 | MelatiStringWriter sw = getStringWriter(); |
144 | 6 | render(s,limit,sw); |
145 | 6 | return sw.toString(); |
146 | } | |
147 | ||
148 | /** | |
149 | * {@inheritDoc} | |
150 | * @see org.melati.template.MarkupLanguage#rendered(org.melati.poem.Field, int, int) | |
151 | */ | |
152 | public String rendered(Field<?> field, int style, int limit) | |
153 | throws TemplateEngineException { | |
154 | 6 | MelatiStringWriter sw = getStringWriter(); |
155 | 6 | render(field, style, limit, sw); |
156 | 6 | return sw.toString(); |
157 | } | |
158 | ||
159 | /** | |
160 | * {@inheritDoc} | |
161 | * @see org.melati.template.MarkupLanguage#rendered(org.melati.poem.Field, int) | |
162 | */ | |
163 | public String rendered(Field<?> field, int style) | |
164 | throws TemplateEngineException { | |
165 | 6 | MelatiStringWriter sw = getStringWriter(); |
166 | 6 | render(field, style, FIELD_POSSIBILITIES_LIMIT, sw); |
167 | 6 | return sw.toString(); |
168 | } | |
169 | ||
170 | /** | |
171 | * {@inheritDoc} | |
172 | * @see org.melati.template.MarkupLanguage#rendered(java.lang.Object) | |
173 | */ | |
174 | public String rendered(Object o) { | |
175 | 6680 | MelatiStringWriter sw = getStringWriter(); |
176 | 6680 | if (o instanceof String) |
177 | 4995 | render((String)o, sw); |
178 | 1685 | else if (o instanceof Field) |
179 | 1496 | render((Field<?>)o, sw); |
180 | else | |
181 | 189 | render(o, sw); |
182 | 6642 | return sw.toString(); |
183 | } | |
184 | ||
185 | /** | |
186 | * {@inheritDoc} | |
187 | * @see org.melati.template.MarkupLanguage#renderedMarkup(java.lang.String) | |
188 | */ | |
189 | public String renderedMarkup(String s) { | |
190 | 6 | MelatiStringWriter sw = getStringWriter(); |
191 | 6 | renderMarkup(s, sw); |
192 | 5 | return sw.toString(); |
193 | } | |
194 | ||
195 | /** | |
196 | * Render a String in a MarkupLanguage specific way, limiting it's length. | |
197 | * Render to a supplied MelatiWriter. | |
198 | * | |
199 | * @param s - the string to be rendered | |
200 | * @param writer - the MelatiWriter to render this String to | |
201 | * @param limit - the length to trim the string to | |
202 | */ | |
203 | protected void render(String s, int limit, MelatiWriter writer) { | |
204 | 3286 | render(s.length() < limit + 3 ? s : s.substring(0, limit) + "...", writer); |
205 | 3286 | } |
206 | ||
207 | /** | |
208 | * Render a String in a MarkupLanguage specific way | |
209 | * to a supplied MelatiWriter. | |
210 | * | |
211 | * @param s - the string to be rendered | |
212 | * @param writer - the MelatiWriter to render this String to | |
213 | */ | |
214 | protected abstract void render(String s, MelatiWriter writer); | |
215 | ||
216 | /** | |
217 | * Render a markup fragment in a MarkupLanguage specific way | |
218 | * to a supplied MelatiWriter. | |
219 | * | |
220 | * @param s - the fragment to be rendered | |
221 | * @param writer - the MelatiWriter to render this String to | |
222 | */ | |
223 | protected abstract void renderMarkup(String s, MelatiWriter writer); | |
224 | ||
225 | /** | |
226 | * Render a Field Object in a MarkupLanguage specific way, | |
227 | * rendering to supplied MelatiWriter. | |
228 | * | |
229 | * @param field - the Field to be rendered | |
230 | * @param writer - the MelatiWriter to render this Object to | |
231 | */ | |
232 | protected void render(Field<?> field, MelatiWriter writer) { | |
233 | 1496 | render(field, DateFormat.MEDIUM, FIELD_POSSIBILITIES_LIMIT, writer); |
234 | 1496 | } |
235 | ||
236 | /** | |
237 | * Render a Field Object in a MarkupLanguage specific way, | |
238 | * rendering to supplied MelatiWriter. | |
239 | * | |
240 | * @param field - the Field to be rendered | |
241 | * @param style - a style to format this Field. | |
242 | * @see org.melati.poem.DatePoemType#stringOfCooked | |
243 | * (java.lang.Object,org.melati.poem.PoemLocale, int) | |
244 | * @param limit - the length to trim the rendered string to | |
245 | * @param writer - the MelatiWriter to render this Object to | |
246 | */ | |
247 | protected void render(Field<?> field, int style, int limit, MelatiWriter writer) { | |
248 | 3280 | render(field.getCookedString(locale, style), limit, writer); |
249 | 3280 | } |
250 | ||
251 | ||
252 | /** | |
253 | * {@inheritDoc} | |
254 | * @see org.melati.template.MarkupLanguage#renderedStart(org.melati.poem.Field) | |
255 | */ | |
256 | public String renderedStart(Field<?> field) { | |
257 | 1772 | MelatiStringWriter sw = getStringWriter(); |
258 | 1772 | renderStart(field, sw); |
259 | 1772 | return sw.toString(); |
260 | } | |
261 | ||
262 | ||
263 | protected void renderStart(Field<?> field, MelatiWriter writer) { | |
264 | 1772 | render(field, DateFormat.MEDIUM, DATE_FIELD_POSSIBILITIES_LIMIT, writer); |
265 | 1772 | } |
266 | ||
267 | /** | |
268 | * Render an Object in a MarkupLanguage specific way, rendering to | |
269 | * the <code>MelatiWriter</code> supplied by <code>melati.getWriter()</code>. | |
270 | * | |
271 | * @param o - the Object to be rendered | |
272 | * @throws TemplateEngineException - if there is a problem with the | |
273 | * ServletTemplateEngine | |
274 | */ | |
275 | protected void render(Object o) { | |
276 | 8 | MelatiWriter writer = melati.getWriter(); |
277 | 8 | render(o, writer); |
278 | 4 | } |
279 | ||
280 | /** | |
281 | * Render an Object in a MarkupLanguage specific way, rendering to | |
282 | * a supplied Writer. | |
283 | * | |
284 | * NOTE The context always contains objects with the names melati, object and ml | |
285 | * | |
286 | * @param o - the Object to be rendered | |
287 | * @param writer - the MelatiWriter to render this Object to | |
288 | */ | |
289 | protected void render(Object o, MelatiWriter writer) { | |
290 | 146 | if (o == null) |
291 | 5 | throw new NullPointerException(); |
292 | else { | |
293 | 141 | TemplateContext vars = |
294 | 141 | melati.getTemplateEngine().getTemplateContext(); |
295 | 132 | Template templet = |
296 | 132 | templetLoader.templet(melati.getTemplateEngine(), this, o.getClass()); |
297 | 126 | vars.put("object", o); |
298 | 126 | vars.put("melati", melati); |
299 | 126 | vars.put("ml", melati.getMarkupLanguage()); |
300 | 126 | expandTemplet(templet, vars, writer); |
301 | } | |
302 | 116 | } |
303 | ||
304 | ||
305 | // | |
306 | // ========= | |
307 | // Widgets | |
308 | // ========= | |
309 | // | |
310 | ||
311 | /** | |
312 | * {@inheritDoc} | |
313 | * @see org.melati.template.MarkupLanguage#input(org.melati.poem.Field) | |
314 | */ | |
315 | public String input(Field<?> field) | |
316 | throws TemplateEngineException, | |
317 | NotFoundException { | |
318 | 225 | return input(field, null, "", false); |
319 | } | |
320 | ||
321 | /** | |
322 | * {@inheritDoc} | |
323 | * @see org.melati.template.MarkupLanguage#inputAs(org.melati.poem.Field, java.lang.String) | |
324 | */ | |
325 | public String inputAs(Field<?> field, String templetName) | |
326 | throws TemplateEngineException, | |
327 | NotFoundException { | |
328 | 34 | return input(field, templetName, "", false); |
329 | } | |
330 | ||
331 | /** | |
332 | * {@inheritDoc} | |
333 | * @see org.melati.template.MarkupLanguage#searchInput(org.melati.poem.Field, java.lang.String) | |
334 | */ | |
335 | public String searchInput(Field<?> field, String nullValue) | |
336 | throws TemplateEngineException, | |
337 | NotFoundException{ | |
338 | 5 | return input(field, null, nullValue, true); |
339 | } | |
340 | ||
341 | protected String input(Field<?> field, | |
342 | String templetName, | |
343 | String nullValue, | |
344 | boolean overrideNullable) | |
345 | throws NotFoundException { | |
346 | ||
347 | Template templet; | |
348 | 264 | if (templetName == null) |
349 | 230 | templet = templetLoader.templet(melati.getTemplateEngine(), this, field) ; |
350 | else | |
351 | 34 | templet = templetLoader.templet(melati.getTemplateEngine(), this, templetName); |
352 | ||
353 | 252 | TemplateContext vars = |
354 | 252 | melati.getTemplateEngine().getTemplateContext(); |
355 | ||
356 | 252 | if (overrideNullable) { |
357 | 4 | field = field.withNullable(true); |
358 | 4 | vars.put("nullValue", nullValue); |
359 | } | |
360 | ||
361 | 252 | vars.put("melati", melati); |
362 | 252 | vars.put("ml", melati.getMarkupLanguage()); |
363 | 252 | vars.put("object", field); |
364 | 252 | vars.put("field", field); |
365 | 252 | MelatiStringWriter sw = getStringWriter(); |
366 | 252 | melati.getTemplateEngine().expandTemplate(sw, templet,vars); |
367 | ||
368 | 252 | return sw.toString(); |
369 | } | |
370 | ||
371 | ||
372 | /** | |
373 | * Interpolate a templet and write it out. | |
374 | * | |
375 | * @param templet {@link Template} to interpolate | |
376 | * @param tc {@link TemplateContext} against which to instantiate variables | |
377 | * @param out {@link MelatiWriter} to write results to | |
378 | */ | |
379 | protected void expandTemplet(Template templet, TemplateContext tc, | |
380 | MelatiWriter out) { | |
381 | 138 | melati.getTemplateEngine().expandTemplate(out, templet, tc); |
382 | 125 | } |
383 | } | |
384 | ||
385 |