1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.melati.template;
47
48 import org.melati.poem.FieldAttributes;
49 import org.melati.util.MelatiBugMelatiException;
50
51 import java.util.Hashtable;
52
53
54
55
56 public final class ClassNameTempletLoader implements TempletLoader {
57
58
59 private static ClassNameTempletLoader it = null;
60
61
62 private static Hashtable<String,Template> templetForClassCache = new Hashtable<String,Template>();
63
64 private static final Integer FOUND = new Integer(1);
65 private static final Integer NOT_FOUND = new Integer(0);
66 private static Hashtable<String,Integer> lookedupTemplateNames = new Hashtable<String,Integer>();
67
68
69 private ClassNameTempletLoader() {}
70
71
72
73
74 public static ClassNameTempletLoader getInstance() {
75 if (it == null)
76 it = new ClassNameTempletLoader();
77 return it;
78 }
79 protected static String templetsPath(TemplateEngine templateEngine,
80 MarkupLanguage markupLanguage) {
81
82
83
84
85
86
87
88
89
90 return "org/melati/templets/" +
91 markupLanguage.getName() + "/";
92
93 }
94
95
96
97
98 protected static String templetsTempletPath(TemplateEngine templateEngine,
99 MarkupLanguage markupLanguage,
100 String purpose, String name) {
101 if (purpose == null)
102 return
103 templetsPath(templateEngine, markupLanguage) +
104 name +
105 templateEngine.templateExtension();
106 return
107 templetsPath(templateEngine, markupLanguage) +
108 purpose + "/" +
109 name +
110 templateEngine.templateExtension();
111 }
112
113 protected static String classpathTempletPath(Class<?> clazz, String purpose, TemplateEngine templateEngine) {
114 if (purpose == null) {
115 return clazz.getName().replace('.', '/') + templateEngine.templateExtension();
116 } else {
117 return clazz.getPackage().getName().replace('.', '/')
118 + "/" + purpose
119 + "/" + clazz.getSimpleName()
120 + templateEngine.templateExtension();
121 }
122 }
123
124
125
126
127
128
129 public Template templet(TemplateEngine templateEngine,
130 MarkupLanguage markupLanguage, String purpose,
131 String name) throws NotFoundException {
132 return templateEngine.template(templetsTempletPath(templateEngine, markupLanguage,
133 purpose, name));
134 }
135
136
137
138
139
140
141
142 public Template templet(TemplateEngine templateEngine,
143 MarkupLanguage markupLanguage, String name)
144 throws NotFoundException {
145 return templet(templateEngine, markupLanguage, null, name);
146 }
147
148
149
150
151
152
153
154
155
156 public Template templet(TemplateEngine templateEngine,
157 MarkupLanguage markupLanguage, String purpose,
158 Class<?> clazz)
159 throws TemplateEngineException {
160 Class<?> lookupClass = clazz;
161 Template templet = null;
162 Template fromCache = null;
163 String originalCacheKey = cacheKey(templateEngine, markupLanguage, purpose, lookupClass);
164 String lookupCacheKey = originalCacheKey;
165 String lookupPurpose = purpose;
166 while (true) {
167 fromCache = (Template)templetForClassCache.get(lookupCacheKey);
168 if (fromCache != null) {
169 templet = fromCache;
170 break;
171 }
172
173
174
175
176
177
178
179
180 String templetPath = templetsTempletPath(templateEngine, markupLanguage,
181 lookupPurpose, lookupClass.getName());
182 templet = getTemplate(templateEngine, templetPath);
183 if (templet != null)
184 break;
185
186 templetPath = classpathTempletPath(lookupClass, purpose, templateEngine);
187 templet = getTemplate(templateEngine, templetPath);
188 if (templet != null)
189 break;
190
191 if (lookupPurpose != null)
192 lookupPurpose = null;
193 else {
194 lookupClass = lookupClass.getSuperclass();
195 lookupPurpose = purpose;
196 }
197 lookupCacheKey = cacheKey(templateEngine, markupLanguage, lookupPurpose, lookupClass);
198 }
199
200
201
202 if (fromCache == null)
203 templetForClassCache.put(originalCacheKey, templet);
204 if (!lookupCacheKey.equals(originalCacheKey)) {
205 if (templetForClassCache.get(lookupCacheKey) == null)
206 templetForClassCache.put(lookupCacheKey, templet);
207 }
208 return templet;
209 }
210
211 private String cacheKey(TemplateEngine templateEngine,
212 MarkupLanguage markupLanguage,
213 String purpose,
214 Class<?> lookupClass) {
215 return purpose == null ? cacheKey(templateEngine, markupLanguage, lookupClass)
216 : lookupClass + "/" +
217 purpose + "/" +
218 markupLanguage + "/" +
219 templateEngine.getName();
220 }
221
222 private String cacheKey(TemplateEngine templateEngine,
223 MarkupLanguage markupLanguage,
224 Class<?> lookupClass) {
225 return lookupClass +
226 "/" + markupLanguage +
227 "/" + templateEngine.getName();
228 }
229
230 private Template getTemplate(TemplateEngine templateEngine, String templetPath) {
231 Template templet = null;
232 try {
233 Object triedAlready = lookedupTemplateNames.get(templetPath);
234 if (triedAlready != NOT_FOUND) {
235 templet = templateEngine.template(templetPath);
236 lookedupTemplateNames.put(templetPath, FOUND);
237 }
238 } catch (NotFoundException e) {
239 lookedupTemplateNames.put(templetPath, NOT_FOUND);
240 }
241 return templet;
242 }
243
244
245
246
247
248
249
250 public Template templet(TemplateEngine templateEngine,
251 MarkupLanguage markupLanguage, Class<?> clazz) {
252 return templet(templateEngine, markupLanguage, null, clazz);
253 }
254
255
256
257
258
259
260
261
262 public Template templet(TemplateEngine templateEngine,
263 MarkupLanguage markupLanguage,
264 FieldAttributes<?> attributes) {
265 if (attributes.getRenderInfo() != null) {
266 String templetName = attributes.getType().getClass().getName()
267 + "-"
268 + attributes.getRenderInfo();
269 try {
270 return templet(templateEngine, markupLanguage,
271 templetName);
272 } catch (NotFoundException e) {
273 throw new MelatiBugMelatiException(
274 "Templet " + templetName + " not found", e);
275 }
276 } else {
277 return templet(templateEngine, markupLanguage,
278 attributes.getType().getClass());
279 }
280 }
281 }
282
283
284
285
286
287
288
289
290
291