| <?xml version="1.0"?> |
| <!-- |
| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| --> |
| |
| <document> |
| |
| <properties> |
| <title>Unified Templating Service Proposal</title> |
| </properties> |
| |
| <body> |
| |
| <section name="Unified Templating Service"> |
| |
| <p> |
| There are multiple templating services that provide similar functionality, but |
| have different API. This is due to different types of "Context" objects. All |
| these types main"Map" semantics (question: is there any other important |
| functionality in the Contexts?). We could define a single service interface |
| that all of the templating services (WebMacro, Velocity, FreeMarker and JSP at |
| the moment) would implement. Its methods would use Map type to represent a |
| Context or another interface extending or similar to map. The service would |
| include the following methods: |
| </p> |
| |
| <pre> |
| public interface TemplatingService |
| extends Service |
| { |
| public boolean templateExists( String name ); |
| public Map createContext( RunData data ); |
| public Map createContext( ); |
| public Strinq merqeTemplate( String name, Map context ); |
| } |
| </pre> |
| |
| <p> |
| Definition of this common interface would allow creation of new base Modules |
| (Screen, Navigation, Layout and Page) that would take advantage of the |
| templating abstraction provided by the Service. This would make the modules |
| (esp. Screens) contained in the application independent of the particular |
| templating mechanism. |
| </p> |
| |
| <p> |
| I don't know enough about FreeMarker to tell if it can fit into this model. |
| If not, I would even suggest dropping the support for it, as it's user base |
| seems nonexistent. |
| </p> |
| |
| <p> |
| There is one important special case to consider. JSP service is unable to return |
| the results of template merging as a String - they are written to the Response |
| stream directly. To encompass this case in our framework, we could declare that |
| the return value of merge template in this case is a null. The Modules would be |
| subject to the same semantics: a null returned from build() method would mean that |
| data was written to the response directly, and the caller should act accordingly. |
| (an example of such case is the interaction of the Layout and the RawScreen). |
| </p> |
| |
| <p> |
| The special semantics of JSP templating lead in turn to a special Page and Layout |
| module behavior. While the "normal" Layout module executes the Screen module |
| and merges its template before merging it's own template ("prefix" rendering), |
| the JSP Layout needs to wrap Screen rendering in a context tool so that it is |
| executed in the appropriate place in the Layout's markup. ("infix" rendering). |
| The same patterns apply to Page-Layout interaction. We have the option to define |
| JSPPage and JSPLayout Modules, or define InfixPage, InfixLayout and the |
| LayoutRenderer and ScreenRenderer context tools, that will be used with those |
| templating services that write the merging results directly to the Response |
| stream. Note that during the normal Layout processing, the Navigations are |
| subject to "infix" rendering, and the current TemplateNavigation class is a |
| prototype of *Renderer. |
| </p> |
| |
| <p> |
| The unified interface and the Infix* Modules will make adding support for other |
| templating engines easy. This will also make porting applications easier - |
| templates in one templating language can be created, then supporting Turbine |
| modules are created. Later the templates can be converted to another language, |
| and the only change to support that on the code side of things is switching a |
| property in TR.props |
| </p> |
| |
| <p> |
| The template lookup functionality that is currently contained in |
| TemplateService, probably should be contained in the service I'm describing here, |
| probably in an abstract base class. |
| </p> |
| |
| <p> |
| Another class that would be affected by the changes mentioned here is the |
| TempateInfo class. Right now it uses a HashTable to store it's data. |
| Now, thanks to defining the common Context type (or using the Map type |
| in its place), it's possible to turn the runtime typed HashTable entries into |
| compile time typed instance variables. |
| </p> |
| |
| <p> |
| The amount of work needed to port an existing application should not be very large. |
| The applications following the Pull MVC design model would not be affected at all. |
| The traditional Push applications would require changes in the Screen and Navigation |
| classes regarding the names of the Context type and the parent type of the |
| Screen/Navigation in question. These changes can be effectively introduced using an |
| automated tool. |
| </p> |
| |
| <p> |
| The Page and Layout classes would require more in-depth modifications, but a typical |
| application would contain single customized Page and Layout classes, if any. |
| </p> |
| |
| </section> |
| </body> |
| |
| </document> |