View Javadoc

1   package org.apache.turbine.services.template.mapper;
2   
3   
4   /*
5    * Licensed to the Apache Software Foundation (ASF) under one
6    * or more contributor license agreements.  See the NOTICE file
7    * distributed with this work for additional information
8    * regarding copyright ownership.  The ASF licenses this file
9    * to you under the Apache License, Version 2.0 (the
10   * "License"); you may not use this file except in compliance
11   * with the License.  You may obtain a copy of the License at
12   *
13   *   http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing,
16   * software distributed under the License is distributed on an
17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   * KIND, either express or implied.  See the License for the
19   * specific language governing permissions and limitations
20   * under the License.
21   */
22  
23  
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.List;
27  
28  import org.apache.commons.lang.StringUtils;
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.turbine.modules.Assembler;
32  import org.apache.turbine.modules.Loader;
33  import org.apache.turbine.services.template.TemplateService;
34  
35  /**
36   * This mapper tries to map Template names to class names. If no direct match
37   * is found, it tries matches "upwards" in the package hierarchy until either
38   * a match is found or the root is hit. Then it returns the name of the
39   * default class from the TemplateEngineService.
40   *
41   * 1. about.directions.Driving     <- direct matching the template to the class name
42   * 2. about.directions.Default     <- matching the package, class name is Default
43   * 3. about.Default                <- stepping up in the package hierarchy, looking for Default
44   * 4. Default                      <- Class called "Default" without package
45   * 5. VelocityScreen               <- The class configured by the Service (VelocityService) to
46   *
47   * Please note, that no actual packages are searched. This is the scope of the
48   * TemplateEngine Loader which is passed at construction time.
49   *
50   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
51   * @version $Id: ClassMapper.java 1709648 2015-10-20 17:08:10Z tv $
52   */
53  
54  public class ClassMapper
55      extends BaseMapper
56      implements Mapper
57  {
58      /** The loader for actually trying out the package names */
59      private Loader<? extends Assembler> loader = null;
60  
61      /** Logging */
62      private static Log log = LogFactory.getLog(ClassMapper.class);
63  
64      /**
65       * Default C'tor. If you use this C'tor, you must use
66       * the bean setter to set the various properties needed for
67       * this mapper before first usage.
68       */
69      public ClassMapper()
70      {
71      	// empty
72      }
73  
74      /**
75       * Get the Loader value.
76       * @return the Loader value.
77       */
78      public Loader<? extends Assembler> getLoader()
79      {
80          return loader;
81      }
82  
83      /**
84       * Set the Loader value.
85       * @param loader The new Loader value.
86       */
87      public void setLoader(Loader<? extends Assembler> loader)
88      {
89          this.loader = loader;
90          log.debug("Loader is " + this.loader);
91      }
92  
93      /**
94       * Strip off a possible extension, replace all "," with "."
95       * Look through the given package path until a match is found.
96       *
97       * @param template The template name.
98       * @return A class name for the given template.
99       */
100     public String doMapping(String template)
101     {
102         log.debug("doMapping(" + template + ")");
103 
104         // Copy our elements into an array
105         List<String> components
106             = new ArrayList<String>(Arrays.asList(StringUtils.split(
107                                               template,
108                                               String.valueOf(TemplateService.TEMPLATE_PARTS_SEPARATOR))));
109         int componentSize = components.size() - 1 ;
110 
111         // This method never gets an empty string passed.
112         // So this is never < 0
113         String className = components.get(componentSize);
114         components.remove(componentSize--);
115 
116         log.debug("className is " + className);
117 
118         // Strip off a possible Extension
119         int dotIndex = className.lastIndexOf(TemplateService.EXTENSION_SEPARATOR);
120         className = (dotIndex < 0) ? className : className.substring(0, dotIndex);
121 
122         // This is an optimization. If the name we're looking for is
123         // already the default name for the template, don't do a "first run"
124         // which looks for an exact match.
125         boolean firstRun = !className.equals(TemplateService.DEFAULT_NAME);
126 
127         for(;;)
128         {
129             String pkg = StringUtils.join(components.iterator(), String.valueOf(separator));
130             StringBuilder testName = new StringBuilder();
131 
132             log.debug("classPackage is now: " + pkg);
133 
134             if (!components.isEmpty())
135             {
136                 testName.append(pkg);
137                 testName.append(separator);
138             }
139 
140             testName.append((firstRun)
141                 ? className
142                 : TemplateService.DEFAULT_NAME);
143 
144             log.debug("Looking for " + testName);
145             try
146             {
147                 loader.getAssembler(testName.toString());
148                 log.debug("Found it, returning " + testName);
149                 return testName.toString();
150             }
151             catch (Exception e)
152             {
153                 // Not found. Go on.
154             }
155 
156             if (firstRun)
157             {
158                 firstRun = false;
159             }
160             else
161             {
162                 if (components.isEmpty())
163                 {
164                     break; // for(;;)
165                 }
166                 components.remove(componentSize--);
167             }
168         }
169 
170         log.debug("Returning default");
171         return getDefaultName(template);
172     }
173 }
174 
175 
176 
177