##### Coverage Report - org.melati.template.ClassNameTempletLoader

Classes in this File | Line Coverage | Branch Coverage | Complexity
ClassNameTempletLoader |
100% | 65/65
100% | 24/24
| 2.3846153846153846;2.385

1 |  |
     /*
2 |  |
      * $Source: /usr/cvsroot/melati/melati/src/site/resources/withWebmacro/org.melati.template.ClassNameTempletLoader.html,v $
3 |  |
      * $Revision: 1.1 $
4 |  |
      *
5 |  |
      * Copyright (C) 2000 William Chesters
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 |  |
      *     William Chesters <williamc At paneris.org>
42 |  |
      *     http://paneris.org/~williamc
43 |  |
      *     Obrechtstraat 114, 2517VX Den Haag, The Netherlands
44 |  |
      */
45 |  |
46 |  |
     package org.melati.template;
47 |  |
48 |  |
     import java.util.Hashtable;
49 |  |
50 |  |
     import org.melati.poem.FieldAttributes;
51 |  |
     import org.melati.util.MelatiBugMelatiException;
52 |  |
53 |  |
     /**
54 |  |
      * Load a template to render an object based upon the object's class.
55 |  |
      */
56 |  |
     public final class ClassNameTempletLoader implements TempletLoader {
57 |  |
58 |  |
       /** The instance. */
59 | 2 |
       private static ClassNameTempletLoader it = null;
60 |  |
61 |  |
       // NOTE It is not expected that templates will be added at runtime.
62 | 2 |
       private static Hashtable<String,Template> templetForClassCache = new Hashtable<String,Template>();
63 |  |
64 | 2 |
       private static final Integer FOUND = new Integer(1);
65 | 2 |
       private static final Integer NOT_FOUND = new Integer(0);
66 | 2 |
       private static Hashtable<String,Integer> lookedupTemplateNames = new Hashtable<String,Integer>();
67 |  |
68 |  |
       /** Disable instantiation. */
69 | 2 |
       private ClassNameTempletLoader() {}
70 |  |
71 |  |
       /**
72 |  |
        * @return the instance
73 |  |
        */
74 |  |
       public static ClassNameTempletLoader getInstance() {
75 | 932 |
         if (it == null)
76 | 2 |
           it = new ClassNameTempletLoader();
77 | 932 |
         return it;
78 |  |
       }
79 |  |
       protected static String templetsPath(TemplateEngine templateEngine,
80 |  |
                                     MarkupLanguage markupLanguage) {
81 |  |
         /*
82 |  |
         // Fails to find templates in jars!!
83 |  |
         return "org" + File.separatorChar +
84 |  |
                "melati" + File.separatorChar +
85 |  |
                "template" + File.separatorChar +
86 |  |
                 templateEngine.getName() + File.separatorChar +
87 |  |
                "templets" + File.separatorChar +
88 |  |
                 markupLanguage.getName() + File.separatorChar;
89 |  |
         */
90 | 696 |
         return "org/melati/templets/" +
91 |  |
                markupLanguage.getName() + "/";
92 |  |
93 |  |
         }
94 |  |
95 |  |
       /**
96 |  |
        * @return the path in the templets directory
97 |  |
        */
98 |  |
       protected static String templetsTempletPath(TemplateEngine templateEngine,
99 |  |
                                    MarkupLanguage markupLanguage,
100 |  |
                                    String purpose, String name) {
101 | 696 |
         if (purpose == null)
102 | 654 |
           return
103 |  |
                      templetsPath(templateEngine, markupLanguage) +
104 |  |
                      name +
105 |  |
                      templateEngine.templateExtension();
106 | 42 |
         return
107 |  |
                    templetsPath(templateEngine, markupLanguage) +
108 |  |
                    purpose + "/" +
109 |  |
                    name +
110 |  |
                    templateEngine.templateExtension();
111 |  |
       }
112 |  |
113 |  |
       protected static String classpathTempletPath(Class<?> clazz, TemplateEngine templateEngine) {
114 | 474 |
         return clazz.getName().replace('.', '/') + templateEngine.templateExtension();
115 |  |
       }
116 |  |
       /**
117 |  |
        * Get a templet by name, with optional purpose.
118 |  |
        *
119 |  |
        * {@inheritDoc}
120 |  |
        * @see TempletLoader#templet(TemplateEngine, AbstractMarkupLanguage, String, String)
121 |  |
        */
122 |  |
       public Template templet(TemplateEngine templateEngine,
123 |  |
                               MarkupLanguage markupLanguage, String purpose,
124 |  |
                               String name) throws NotFoundException {
125 | 118 |
         return templateEngine.template(templetsTempletPath(templateEngine, markupLanguage,
126 |  |
             purpose, name));
127 |  |
       }
128 |  |
129 |  |
       /**
130 |  |
        * Get a templet by its name, looking only in the templets directory.
131 |  |
        *
132 |  |
        * {@inheritDoc}
133 |  |
        * @see TempletLoader#templet(TemplateEngine, MarkupLanguage, String)
134 |  |
        */
135 |  |
       public Template templet(TemplateEngine templateEngine,
136 |  |
                               MarkupLanguage markupLanguage, String name)
137 |  |
           throws NotFoundException {
138 | 118 |
         return templet(templateEngine, markupLanguage, null, name);
139 |  |
       }
140 |  |
141 |  |
       /**
142 |  |
        * Get a templet based upon class name and optional purpose,
143 |  |
        * looking in the templets directory and also the classpath.
144 |  |
        *
145 |  |
        * {@inheritDoc}
146 |  |
        * @see TempletLoader#templet(TemplateEngine, MarkupLanguage,
147 |  |
        *                            String, Class)
148 |  |
        */
149 |  |
       public Template templet(TemplateEngine templateEngine,
150 |  |
                               MarkupLanguage markupLanguage, String purpose,
151 |  |
                               Class<?> clazz)
152 |  |
           throws TemplateEngineException {
153 | 690 |
         Class<?> lookupClass = clazz;
154 | 690 |
         Template templet = null;
155 | 690 |
         Template fromCache = null;
156 | 690 |
         String originalCacheKey = cacheKey(templateEngine, markupLanguage, purpose, lookupClass);
157 | 690 |
         String lookupCacheKey = originalCacheKey;
158 | 690 |
         String lookupPurpose = purpose;
159 |  |
         while (true) {
160 | 1136 |
           fromCache = (Template)templetForClassCache.get(lookupCacheKey);
161 | 1136 |
           if (fromCache != null) {
162 | 558 |
             templet = fromCache;
163 | 558 |
             break;
164 |  |
           }
165 |  |
           //templet = getSpecialTemplate(lookupClass, lookupPurpose, markupLanguage, templateEngine);
166 |  |
           //if (templet != null)
167 |  |
           //  break;
168 |  |
169 |  |
           // Try to find one in the templets directory
170 | 578 |
           String templetPath = templetsTempletPath(templateEngine, markupLanguage,
171 |  |
                   lookupPurpose, lookupClass.getName());
172 | 578 |
           templet = getTemplate(templateEngine, templetPath);
173 | 556 |
           if (templet != null)
174 | 82 |
             break;
175 |  |
           // Try to find one on classpath
176 | 474 |
           templetPath = classpathTempletPath(lookupClass, templateEngine);
177 | 474 |
           templet = getTemplate(templateEngine, templetPath);
178 | 462 |
           if (templet != null)
179 | 16 |
             break;
180 |  |
181 | 446 |
           if (lookupPurpose != null)
182 | 30 |
             lookupPurpose = null;
183 |  |
           else {
184 | 416 |
             lookupClass = lookupClass.getSuperclass();
185 | 416 |
             lookupPurpose = purpose;
186 |  |
           }
187 | 446 |
           lookupCacheKey = cacheKey(templateEngine, markupLanguage, lookupPurpose, lookupClass);
188 | 446 |
         }
189 |  |
         // We should have at last found Object template
190 |  |
         //if (templet == null)
191 |  |
         //  throw new MelatiBugMelatiException("Cannot even find template for Object");
192 | 656 |
         System.err.println(lookupCacheKey);
193 | 656 |
         if (fromCache == null)
194 | 98 |
           templetForClassCache.put(originalCacheKey, templet);
195 | 656 |
         if (!lookupCacheKey.equals(originalCacheKey)) {
196 | 196 |
           if (templetForClassCache.get(lookupCacheKey) == null)
197 | 40 |
             templetForClassCache.put(lookupCacheKey, templet);
198 |  |
         }
199 | 656 |
         return templet;
200 |  |
       }
201 |  |
202 |  |
       private String cacheKey(TemplateEngine templateEngine,
203 |  |
           MarkupLanguage markupLanguage,
204 |  |
           String purpose,
205 |  |
           Class<?> lookupClass) {
206 | 1136 |
         return  purpose == null ? cacheKey(templateEngine, markupLanguage, lookupClass)
207 |  |
                                 : lookupClass + "/" +
208 |  |
                                    purpose + "/" +
209 |  |
                                    markupLanguage + "/" +
210 |  |
                                    templateEngine.getName();
211 |  |
       }
212 |  |
213 |  |
       private String cacheKey(TemplateEngine templateEngine,
214 |  |
           MarkupLanguage markupLanguage,
215 |  |
           Class<?> lookupClass) {
216 | 1086 |
         return lookupClass +
217 |  |
                "/" + markupLanguage +
218 |  |
                "/" + templateEngine.getName();
219 |  |
       }
220 |  |
221 |  |
       private Template getTemplate(TemplateEngine templateEngine, String templetPath)  {
222 | 1052 |
         Template templet = null;
223 |  |
         try {
224 | 1052 |
           Object triedAlready = lookedupTemplateNames.get(templetPath);
225 | 1052 |
           if (triedAlready != NOT_FOUND) {
226 | 584 |
             templet = templateEngine.template(templetPath);
227 | 98 |
             lookedupTemplateNames.put(templetPath, FOUND);
228 |  |
           }
229 | 452 |
         } catch (NotFoundException e) {
230 | 452 |
           lookedupTemplateNames.put(templetPath, NOT_FOUND);
231 | 566 |
         }
232 | 1018 |
         return templet;
233 |  |
       }
234 |  |
235 |  |
       /**
236 |  |
        * Get a templet for a class.
237 |  |
        *
238 |  |
        * {@inheritDoc}
239 |  |
        * @see TempletLoader#templet(TemplateEngine, MarkupLanguage, Class)
240 |  |
        */
241 |  |
       public Template templet(TemplateEngine templateEngine,
242 |  |
                               MarkupLanguage markupLanguage, Class<?> clazz) {
243 | 668 |
         return templet(templateEngine, markupLanguage, null, clazz);
244 |  |
       }
245 |  |
246 |  |
       /**
247 |  |
        * Get a templet either from the classname concatenated with
248 |  |
        * FieldAttributes.RenederInfo or the class name.
249 |  |
        *
250 |  |
        * {@inheritDoc}
251 |  |
        * @see TempletLoader#templet(TemplateEngine,MarkupLanguage,FieldAttributes)
252 |  |
        */
253 |  |
       public Template templet(TemplateEngine templateEngine,
254 |  |
                               MarkupLanguage markupLanguage,
255 |  |
                               FieldAttributes attributes) {
256 | 460 |
         if (attributes.getRenderInfo() != null) {
257 | 44 |
           String templetName = attributes.getType().getClass().getName()
258 |  |
               + "-"
259 |  |
               + attributes.getRenderInfo();
260 |  |
           try {
261 | 44 |
             return templet(templateEngine, markupLanguage,
262 |  |
                     templetName);
263 | 4 |
           } catch (NotFoundException e) {
264 | 4 |
             throw new MelatiBugMelatiException(
265 |  |
                     "Templet " + templetName  + " not found", e);
266 |  |
           }
267 |  |
         } else {
268 | 416 |
             return templet(templateEngine, markupLanguage,
269 |  |
                     attributes.getType().getClass());
270 |  |
         }
271 |  |
       }
272 |  |
     }
273 |  |
274 |  |
275 |  |
276 |  |
277 |  |
278 |  |
279 |  |
280 |  |
281 |  |
282 |  |