Coverage Report - org.melati.template.ClassNameTempletLoader
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassNameTempletLoader
100%
75/75
100%
24/24
2.385
 
 1  
 /*
 2  
  * $Source$
 3  
  * $Revision$
 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  1
   private static ClassNameTempletLoader it = null;
 60  
 
 61  
   // NOTE It is not expected that templates will be added at runtime.
 62  1
   private static Hashtable<String,Template> templetForClassCache = new Hashtable<String,Template>();
 63  
   
 64  1
   private static final Integer FOUND = new Integer(1);
 65  1
   private static final Integer NOT_FOUND = new Integer(0);
 66  1
   private static Hashtable<String,Integer> lookedupTemplateNames = new Hashtable<String,Integer>();
 67  
 
 68  
   /** Disable instantiation. */
 69  1
   private ClassNameTempletLoader() {}
 70  
 
 71  
   /**
 72  
    * @return the instance
 73  
    */
 74  
   public static ClassNameTempletLoader getInstance() {
 75  524
     if (it == null)
 76  1
       it = new ClassNameTempletLoader();
 77  524
     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  405
     return "org/melati/templets/" + 
 91  405
            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  405
     if (purpose == null)
 102  382
       return 
 103  382
         templetsPath(templateEngine, markupLanguage) + 
 104  
         name +
 105  382
         templateEngine.templateExtension();
 106  23
     return 
 107  23
         templetsPath(templateEngine, markupLanguage) + 
 108  
         purpose + "/" + 
 109  
         name +
 110  23
         templateEngine.templateExtension();
 111  
   }
 112  
 
 113  
   protected static String classpathTempletPath(Class<?> clazz, TemplateEngine templateEngine) { 
 114  298
     return clazz.getName().replace('.', '/') + templateEngine.templateExtension();
 115  
   }
 116  
   /**
 117  
    * Get a templet by name, with optional purpose. 
 118  
    * 
 119  
    * @see TempletLoader#templet
 120  
    */
 121  
   public Template templet(TemplateEngine templateEngine,
 122  
                           MarkupLanguage markupLanguage, String purpose,
 123  
                           String name) throws NotFoundException {
 124  59
     return templateEngine.template(templetsTempletPath(templateEngine, markupLanguage,
 125  
         purpose, name));
 126  
   }
 127  
 
 128  
   /**
 129  
    * Get a templet by its name, looking only in the templets directory.
 130  
    * 
 131  
    * {@inheritDoc}
 132  
    * @see TempletLoader#templet(TemplateEngine, MarkupLanguage, String)
 133  
    */
 134  
   public Template templet(TemplateEngine templateEngine,
 135  
                           MarkupLanguage markupLanguage, String name) 
 136  
       throws NotFoundException {
 137  59
     return templet(templateEngine, markupLanguage, null, name);
 138  
   }
 139  
 
 140  
   /**
 141  
    * Get a templet based upon class name and optional purpose, 
 142  
    * looking in the templets directory and also the classpath.
 143  
    * 
 144  
    * {@inheritDoc}
 145  
    * @see TempletLoader#templet(TemplateEngine, MarkupLanguage, 
 146  
    *                            String, Class)
 147  
    */
 148  
   public Template templet(TemplateEngine templateEngine,
 149  
                           MarkupLanguage markupLanguage, String purpose,
 150  
                           Class<?> clazz)
 151  
       throws TemplateEngineException {
 152  369
     Class<?> lookupClass = clazz;
 153  369
     Template templet = null;
 154  369
     Template fromCache = null;
 155  369
     String originalCacheKey = cacheKey(templateEngine, markupLanguage, purpose, lookupClass);
 156  369
     String lookupCacheKey = originalCacheKey;
 157  369
     String lookupPurpose = purpose;
 158  
     while (true) {
 159  650
       fromCache = (Template)templetForClassCache.get(lookupCacheKey);
 160  650
       if (fromCache != null) {
 161  304
         templet = fromCache;
 162  304
         break;
 163  
       } 
 164  
       //templet = getSpecialTemplate(lookupClass, lookupPurpose, markupLanguage, templateEngine);
 165  
       //if (templet != null)
 166  
       //  break;
 167  
       
 168  
       // Try to find one in the templets directory
 169  692
       String templetPath = templetsTempletPath(templateEngine, markupLanguage,
 170  346
               lookupPurpose, lookupClass.getName());
 171  346
       templet = getTemplate(templateEngine, templetPath);
 172  343
       if (templet != null)
 173  45
         break;
 174  
       // Try to find one on classpath
 175  298
       templetPath = classpathTempletPath(lookupClass, templateEngine);
 176  298
       templet = getTemplate(templateEngine, templetPath);
 177  291
       if (templet != null)
 178  10
         break;
 179  
       
 180  281
       if (lookupPurpose != null)
 181  18
         lookupPurpose = null;
 182  
       else { 
 183  263
         lookupClass = lookupClass.getSuperclass();
 184  263
         lookupPurpose = purpose;
 185  
       }
 186  281
       lookupCacheKey = cacheKey(templateEngine, markupLanguage, lookupPurpose, lookupClass);
 187  281
     }
 188  
     // We should have at last found Object template    
 189  
     //if (templet == null)
 190  
     //  throw new MelatiBugMelatiException("Cannot even find template for Object");
 191  359
     System.err.println(lookupCacheKey);
 192  359
     if (fromCache == null)
 193  55
       templetForClassCache.put(originalCacheKey, templet);
 194  359
     if (!lookupCacheKey.equals(originalCacheKey)) { 
 195  120
       if (templetForClassCache.get(lookupCacheKey) == null) 
 196  23
         templetForClassCache.put(lookupCacheKey, templet);
 197  
     } 
 198  359
     return templet;
 199  
   }
 200  
 
 201  
   private String cacheKey(TemplateEngine templateEngine, 
 202  
       MarkupLanguage markupLanguage, 
 203  
       String purpose, 
 204  
       Class<?> lookupClass) {
 205  650
     return  purpose == null ? cacheKey(templateEngine, markupLanguage, lookupClass) 
 206  
                             : lookupClass + "/" + 
 207  
                                purpose + "/" + 
 208  
                                markupLanguage + "/" + 
 209  29
                                templateEngine.getName();
 210  
   }
 211  
   
 212  
   private String cacheKey(TemplateEngine templateEngine, 
 213  
       MarkupLanguage markupLanguage, 
 214  
       Class<?> lookupClass) {
 215  621
     return lookupClass + 
 216  
            "/" + markupLanguage + 
 217  621
            "/" + templateEngine.getName();
 218  
   }
 219  
 
 220  
   private Template getTemplate(TemplateEngine templateEngine, String templetPath)  { 
 221  644
     Template templet = null;
 222  
     try {
 223  644
       Object triedAlready = lookedupTemplateNames.get(templetPath);
 224  644
       if (triedAlready != NOT_FOUND) {
 225  351
         templet = templateEngine.template(templetPath);
 226  55
         lookedupTemplateNames.put(templetPath, FOUND);
 227  
       } 
 228  286
     } catch (NotFoundException e) {
 229  286
       lookedupTemplateNames.put(templetPath, NOT_FOUND);
 230  348
     }
 231  634
     return templet;
 232  
   }
 233  
 
 234  
   /**
 235  
    * Get a templet for a class.
 236  
    * 
 237  
    * {@inheritDoc}
 238  
    * @see TempletLoader#templet(TemplateEngine, MarkupLanguage, Class)
 239  
    */
 240  
   public Template templet(TemplateEngine templateEngine,
 241  
                           MarkupLanguage markupLanguage, Class<?> clazz) {
 242  356
     return templet(templateEngine, markupLanguage, null, clazz);
 243  
   }
 244  
 
 245  
   /**
 246  
    * Get a templet either from the classname concatenated with 
 247  
    * FieldAttributes.RenederInfo or the class name.
 248  
    * 
 249  
    * {@inheritDoc}
 250  
    * @see TempletLoader#templet(TemplateEngine,MarkupLanguage,FieldAttributes)
 251  
    */
 252  
   public Template templet(TemplateEngine templateEngine,
 253  
                           MarkupLanguage markupLanguage,
 254  
                           FieldAttributes<?> attributes) {
 255  230
     if (attributes.getRenderInfo() != null) {
 256  22
       String templetName = attributes.getType().getClass().getName() 
 257  
           + "-"
 258  22
           + attributes.getRenderInfo();
 259  
       try {
 260  22
         return templet(templateEngine, markupLanguage, 
 261  
                 templetName);
 262  2
       } catch (NotFoundException e) {
 263  2
         throw new MelatiBugMelatiException(
 264  
                 "Templet " + templetName  + " not found", e);
 265  
       }
 266  
     } else {
 267  416
         return templet(templateEngine, markupLanguage,
 268  208
                 attributes.getType().getClass());
 269  
     }
 270  
   }
 271  
 }
 272  
 
 273  
 
 274  
 
 275  
 
 276  
 
 277  
 
 278  
 
 279  
 
 280  
 
 281