Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: nextapp/echoservlet/Template.java


1   /* 
2    * This file is part of the Echo Web Application Framework (hereinafter "Echo").
3    * Copyright (C) 2002-2004 NextApp, Inc.
4    *
5    * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6    *
7    * The contents of this file are subject to the Mozilla Public License Version
8    * 1.1 (the "License"); you may not use this file except in compliance with
9    * the License. You may obtain a copy of the License at
10   * http://www.mozilla.org/MPL/
11   *
12   * Software distributed under the License is distributed on an "AS IS" basis,
13   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14   * for the specific language governing rights and limitations under the
15   * License.
16   *
17   * Alternatively, the contents of this file may be used under the terms of
18   * either the GNU General Public License Version 2 or later (the "GPL"), or
19   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20   * in which case the provisions of the GPL or the LGPL are applicable instead
21   * of those above. If you wish to allow use of your version of this file only
22   * under the terms of either the GPL or the LGPL, and not to allow others to
23   * use your version of this file under the terms of the MPL, indicate your
24   * decision by deleting the provisions above and replace them with the notice
25   * and other provisions required by the GPL or the LGPL. If you do not delete
26   * the provisions above, a recipient may use your version of this file under
27   * the terms of any one of the MPL, the GPL or the LGPL.
28   */
29  
30  package nextapp.echoservlet;
31  
32  import java.io.IOException;
33  import java.io.PrintWriter;
34  import java.io.Serializable;
35  import java.util.ArrayList;
36  import java.util.List;
37  
38  import nextapp.echoservlet.util.ContentType;
39  import nextapp.echoservlet.util.Extensions;
40  import nextapp.echoservlet.util.JavaScriptCompressor;
41  import nextapp.echoservlet.util.Resource;
42  
43  /**
44   * A service which produces templated text output.  Templates are used in 
45   * cases where the server must render a mostly static document that contains
46   * text that may vary.  This service is similar to <code>StaticText</code>,
47   * but offers the ability to have dynamically inserted text at specified
48   * points.  A dynamic area is specified by adding a &quot;variable name&quot;
49   * to the template.  Variables names are enclosed in dollar signs.<br>
50   * <br>
51   * The following example document shows how a Template can be used:<br>
52   * <br>
53   * <code>In the year $Year$, annual sales were $$$AnnualSales$.</code><br>
54   * <br>
55   * This sample has two variables, &quot;Year&quot; and &quot;Annual 
56   * Sales&quot;.  The double dollar sign will be rendered as a single dollar 
57   * sign.  The variable data will be extracted from the renderer's 
58   * <code>VariableData</code> object.
59   */
60  public class Template 
61  implements Service, Serializable {
62  
63      private static final String MARKERSTRING = "$";
64      
65      /**
66       * Creates a <code>Template</code> object by way of a resource name.  
67       * The content type will be determined from the resource's extension.
68       * JavaScript resources will be compressed.
69       *
70       * @param resourceName The name of the resource from which to create the
71       *        <code>StaticText</code> object.
72       * @return A <code>Template</code> object containing the content of the
73       *         specified resource.
74       * @deprecated The createFromResource(String, String) method
75       *             should be used instead.  Use of this version may result
76       *             in errors if applications are migrated between VMs,
77       *             due to the Service having a different identifier on each VM.
78       */
79      public static Template createFromResource(String resourceName) {
80          return createFromResource(null, resourceName);
81      }
82  
83      /**
84       * Creates a <code>Template</code> object by way of a resource name.  
85       * The content type will be determined from the resource's extension.
86       * JavaScript resources will be compressed.
87       *
88       * @param identifier A unique identifier for this service.
89       * @param resourceName The name of the resource from which to create the
90       *        <code>StaticText</code> object.
91       * @return A <code>Template</code> object containing the content of the
92       *         specified resource.
93       */
94      public static Template createFromResource(String identifier, String resourceName) {
95          ContentType contentType = Extensions.getFileNameContentType(resourceName);
96          String resource = Resource.getResourceAsString(resourceName);
97          if (contentType.equals(ContentType.TEXT_JAVASCRIPT)) {
98              resource = JavaScriptCompressor.compress(resource);
99          }
100         Template template =  new Template(identifier, contentType, resource);
101         return template;
102     }
103 
104     private String[] staticSections = null;
105     private String[] fieldNames = null;
106     
107     private ContentType contentType = null;
108     private Id id = null;
109 
110     /**
111      * Creates a content template from the given String.
112      * 
113      * @param contentType The content type of the output.
114      * @param templateData A String containing the template data.
115      * @deprecated The Template(String, ContentType, String) constructor
116      *             should be used instead.  Use of this version may result
117      *             in errors if applications are migrated between VMs,
118      *             due to the Service having a different identifier on each VM.
119      */
120     public Template(ContentType contentType, String templateData) {
121         this(null, contentType, templateData);
122     }
123     
124     /**
125      * Creates a content template from the given String.
126      * 
127      * @param contentType The content type of the output.
128      * @param templateData A String containing the template data.
129      * @param identifier A unique identifier for this service.
130      */
131     public Template(String identifier, ContentType contentType, String templateData) {
132         super();
133         
134         if (identifier == null) {
135             id = new Id();
136         } else {
137             id = new Id(identifier);
138         }
139         this.contentType = contentType;
140         
141         List fieldNameList = new ArrayList();
142         List staticSectionList = new ArrayList();
143         
144         int startPosition = 0;
145         int endPosition = 0;
146         do {
147             // Search for next field name
148             endPosition = templateData.indexOf(MARKERSTRING, startPosition);
149             
150             // Add static text up to variable to list of static content.
151             if (endPosition == -1) {
152                 staticSectionList.add(templateData.substring(startPosition));
153             } else {
154                 staticSectionList.add(templateData.substring(startPosition, endPosition));
155             }
156             
157             if (endPosition != -1) {
158                 // determine variable name.
159                 startPosition = endPosition + 1;
160                 endPosition = templateData.indexOf(MARKERSTRING, startPosition);
161                 
162                 if (endPosition == startPosition) {
163                     // MARKERSTRING detected twice, therefore MARKERSTRING is added to last static
164                     // content section.
165                     staticSectionList.set(staticSectionList.size() - 1, 
166                             staticSectionList.get(staticSectionList.size() - 1) + MARKERSTRING);
167                 } else if (endPosition == -1) {
168                     // MARKERSTRING was not found again, meaning document is not valid.
169                     throw new IllegalArgumentException("Data contains unterminated variable string.");
170                 } else {
171                     // Add field name to list
172                     fieldNameList.add(templateData.substring(startPosition, endPosition));
173                 }
174                 
175                 startPosition = endPosition + 1;
176             }
177         } while (endPosition != -1);
178         
179         staticSections = (String[]) staticSectionList.toArray(new String[staticSectionList.size()]);
180         fieldNames = (String[]) fieldNameList.toArray(new String[fieldNameList.size()]);
181     }
182     
183     /**
184      * Returns the content type.
185      *
186      * @return The content type.
187      */
188     public ContentType getContentType() {
189         return contentType;
190     }
191     
192     /**
193      * @see nextapp.echoservlet.Service#getId()
194      */
195     public Id getId() {
196         return id;
197     }
198     
199     /**
200      * @see nextapp.echoservlet.Service#service(Connection)
201      */
202     public void service(Connection conn) 
203     throws IOException {
204         conn.setContentType(contentType);
205         PrintWriter pw = conn.getWriter();
206         
207         VariableData variableData = conn.getVariableData();
208         String customField = null;
209         for (int index = 0; index < staticSections.length; ++index) {
210             if (staticSections[index] != null) {
211                 pw.write(staticSections[index]);
212             }
213             if (index < fieldNames.length && fieldNames[index] != null) {
214                 customField = variableData.get(fieldNames[index]);
215                 if (customField != null) {
216                     pw.write(customField);
217                 }
218             }
219         }
220         
221         pw.close();
222     }
223     
224     /**
225      * Renders the content template as a String.  Should be used only for 
226      * debugging purposes.
227      *
228      * @return A String representation of the template.
229      */
230     public String toString() {
231         StringBuffer sb = new StringBuffer();
232     
233         for (int index = 0; index < staticSections.length; ++index) {
234             if (staticSections[index] != null) {
235                 sb.append("STATIC: " + staticSections[index]);
236             }
237             sb.append("\n");
238             if (fieldNames.length - 1 >= index && fieldNames[index] != null) {
239                 sb.append("DYNAMIC: \"" + fieldNames[index] + "\"");
240             }
241             sb.append("\n");
242         }
243         
244         return sb.toString();
245     }
246 }