Coverage Report - org.melati.template.ClassNameTempletLoader
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassNameTempletLoader
100%
65/65
100%
24/24
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