KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > cofax > WysiwygTemplate


1 /*
2  * WysiwygTemplate is part of the Cofax content management system library.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Please see http://www.cofax.org for contact information and other related informaion.
19  *
20  * $Header: /cvsroot/cofax/cofax/src/org/cofax/WysiwygTemplate.java,v 1.11.2.1 2006/12/11 16:28:43 fxrobin Exp $
21  */

22
23 package org.cofax;
24
25 import java.io.*;
26 import java.util.*;
27 import javax.servlet.http.*;
28 import java.text.SimpleDateFormat JavaDoc;
29
30 /**
31  * A template processor written for Cofax. It can also be re-used in other
32  * applications. It handles template files in a format called the "WYSIWYG
33  * Template format". Templates in this format are plain html files with comment
34  * tags indicating where the data is to be inserted. This is a simple to use yet
35  * powerful templating system that requires only html knowledge. Another feature
36  * of these templates is that they can be previewed in a browser and editing
37  * using any html editing tool. The name wysiwyg comes from the ability of being
38  * able to use dummy to get a realistic preview of what the pages that use this
39  * template will look like. Using this template system saves the philly.com and
40  * some other KnightRidder.com staff lots of time. Cofax separates design from
41  * content and programming.
42  * <p>
43  *
44  * There is no mention of the <code>WysiwygTemplate</code> class in
45  * <code>CofaxServlet</code> . <code>TemplateProcessor</code> classes are
46  * listed in the configuration.
47  * </p>
48  *
49  * @author Rajiv Pant
50  * @author Karl Martino
51  * @author Sam Cohen
52  * @created April 19, 2002
53  * @version 1.9.7
54  */

55
56 public class WysiwygTemplate extends TemplateProcessor {
57
58     private CofaxPage page;
59
60     private CofaxPage template;
61
62     private HashMap glossary;
63
64     private DataStore db;
65
66     private String JavaDoc servingPage;
67
68     private String JavaDoc servingClient;
69
70     /**
71      * Sets the page attribute of the WysiwygTemplate object
72      *
73      * @param inPage
74      * The new page value
75      */

76     public void setPage(CofaxPage inPage) {
77         page = inPage;
78         Glossary glossaryContainer = page.getGlossary();
79         glossary = glossaryContainer.getKeyValues();
80         servingPage = page.getServingPage();
81         servingClient = page.getServingClient();
82     }
83
84     /**
85      * Sets the template attribute of the WysiwygTemplate object
86      *
87      * @param inTemplate
88      * The new template value
89      */

90     public void setTemplate(CofaxPage inTemplate) {
91         template = inTemplate;
92     }
93
94     /**
95      * Processes template data and sets a CofaxPage when finished.
96      *
97      * @return Description of the Return Value
98      */

99     public final boolean applyTemplate() {
100
101         // headerFormat contains the format to display once, at the beginning,
102
// if rows are returned from the datastore
103
StringBuffer JavaDoc headerFormat = new StringBuffer JavaDoc(CofaxUtil.COMMON_DATA_SIZE);
104         String JavaDoc headerFormatStr = "";
105
106         // displayFormat contains the format to repeat for each row
107
// returned from the datastore
108
StringBuffer JavaDoc displayFormat = new StringBuffer JavaDoc(CofaxUtil.COMMON_DATA_SIZE);
109         String JavaDoc displayFormatStr = "";
110
111         // footerFormat contains the format to display once,
112
// if rows are returned from the datastore
113
StringBuffer JavaDoc footerFormat = new StringBuffer JavaDoc(CofaxUtil.COMMON_DATA_SIZE);
114         String JavaDoc footerFormatStr = "";
115
116         // noArticles contains the format to display if no rows
117
// are returned from the datastore
118
StringBuffer JavaDoc noArticles = new StringBuffer JavaDoc(CofaxUtil.COMMON_DATA_SIZE);
119         String JavaDoc noArticlesStr = "";
120
121         // Get the raw template data and use this to loop through
122
BufferedReader in = new BufferedReader(new StringReader(template.toString()));
123
124         // We will be building and returning parsedTemplate
125
StringBuffer JavaDoc parsedTemplate = new StringBuffer JavaDoc(CofaxUtil.COMMON_DATA_SIZE);
126
127         // Set the status code to bad. Override this on errors, if they occur
128

129         try {
130
131             boolean gotTag = false;
132             boolean addToGlossary = false;
133             boolean success = false;
134
135             int startRow = 0;
136             int numRows = 0;
137             int tagLoc = 0;
138             int firstQuote = 0;
139             int lastQuote = 0;
140             int nameSpaceLoc = 0;
141             int beginNameSpace = 0;
142             int endNameSpace = 0;
143             int paramLoc = 0;
144             int count = 0;
145             int headerLoc = 0;
146             int firstHeaderQuote = 0;
147             int secondHeaderQuote = 0;
148             int valLoc = 0;
149             int thirdHeaderQuote = 0;
150             int fourthHeaderQuote = 0;
151             int shouldParse = 0;
152             int shouldParse2 = 0;
153
154             String JavaDoc tag = "";
155             String JavaDoc nameSpace = "";
156             String JavaDoc line;
157             String JavaDoc tagStatement = "";
158             String JavaDoc key = "";
159             String JavaDoc value = "";
160             String JavaDoc packageResults = "";
161             String JavaDoc headerName = "";
162             String JavaDoc headerValue = "";
163
164             List packageRows = null;
165
166             Iterator rows;
167             Iterator i;
168
169             HashMap row = new HashMap();
170
171             while ((line = in.readLine()) != null) {
172                 // Initilaize tag and tagType
173
tag = "";
174                 nameSpace = "";
175                 tagLoc = 0;
176                 gotTag = false;
177                 addToGlossary = false;
178
179                 tagLoc = line.indexOf("<!-- packageTag action=");
180                 if (tagLoc > -1) {
181                     gotTag = true;
182                 } else {
183                     tagLoc = line.indexOf("<!-- glossaryTag action=");
184                     if (tagLoc > -1) {
185                         gotTag = true;
186                         addToGlossary = true;
187                         headerFormatStr = "";
188                         displayFormatStr = "";
189                         footerFormatStr = "";
190                         noArticlesStr = "";
191                     }
192                 }
193
194                 // If we are in a tag then let's do it....
195
if (gotTag) {
196                     // Get the tag name (action)
197
firstQuote = line.indexOf('"', tagLoc);
198                     lastQuote = line.indexOf('"', firstQuote + 1);
199                     tag = line.substring(firstQuote + 1, lastQuote);
200
201                     // Get nameSpace (optional)
202
nameSpaceLoc = line.indexOf("namespace=");
203                     if (nameSpaceLoc > 0) {
204                         beginNameSpace = line.indexOf('"', nameSpaceLoc);
205                         endNameSpace = line.indexOf('"', beginNameSpace + 1);
206                         nameSpace = line.substring(beginNameSpace + 1, endNameSpace);
207                     } else {
208                         nameSpace = tag;
209                     }
210
211                     while ((line = in.readLine()) != null) {
212
213                         /*
214                          * Read template parameters for this packageTag and
215                          * insert them into the glossary namespaced. <!-- param
216                          * name="paramName" value="value" -->
217                          */

218                         paramLoc = 0;
219                         if (line.indexOf("<!-- param name") > -1) {
220                             success = false;
221                             success = addParamToGlossary(glossary, nameSpace, line);
222
223                         }
224
225                         /*
226                          * get the displayFormat. the displayFormat, when parsed
227                          * with a packageTag's return, repeats for each row
228                          * returned from the datastore. <!-- displayFormat -->
229                          * <li>`someTag:fieldName`</li> <!-- /displayFormat
230                          * -->
231                          */

232                         displayFormat.setLength(0);
233
234                         // Get Display Format message code
235
if (line.indexOf("<!-- displayFormat -->") > -1) {
236                             while ((line = in.readLine()) != null) {
237                                 if (line.indexOf("<!-- /displayFormat -->") > -1) {
238                                     break;
239                                 }
240                                 displayFormat.append(" ");
241                                 displayFormat.append("\n");
242                                 displayFormat.append(line);
243                                 displayFormat.append(CofaxUtil.NEW_LINE);
244                             }
245
246                             displayFormatStr = displayFormat.toString();
247                         }
248
249                         /*
250                          * get the noArticles format. noArticles is returned
251                          * when no rows are sent back from a packageTag call.
252                          * <!-- noArticles --> No rows were returned from the
253                          * database. <!-- /noArticles -->
254                          */

255                         noArticles.setLength(0);
256                         if (line.indexOf("<!-- noArticles -->") > -1) {
257                             while ((line = in.readLine()) != null) {
258
259                                 if (line.indexOf("<!-- /noArticles -->") > -1) {
260                                     break;
261                                 }
262                                 noArticles.append(" ");
263                                 noArticles.append(line);
264                                 noArticles.append(CofaxUtil.NEW_LINE);
265                             }
266
267                             noArticlesStr = noArticles.toString();
268
269                         }
270
271                         /*
272                          * get the headerFormat. the headerFormat is returned
273                          * ONCE, before the displayFormat, only if rows are
274                          * returned from the packageTag call. <!-- headerFormat
275                          * --> <ul> <!-- /headerFormat -->
276                          */

277                         headerFormat.setLength(0);
278                         if (line.indexOf("<!-- headerFormat -->") > -1) {
279                             while ((line = in.readLine()) != null) {
280
281                                 if (line.indexOf("<!-- /headerFormat -->") > -1) {
282                                     break;
283                                 }
284                                 headerFormat.append(" ");
285                                 headerFormat.append(line);
286                                 headerFormat.append(CofaxUtil.NEW_LINE);
287                             }
288
289                             headerFormatStr = headerFormat.toString();
290
291                         }
292
293                         /*
294                          * get the footerFormat. the footerFormat is returned
295                          * ONCE, after the displayFormat, only if rows are
296                          * returned from the packageTag call. <!-- footerFormat
297                          * --> </ul> <!-- /footerFormat -->
298                          */

299                         footerFormat.setLength(0);
300                         if (line.indexOf("<!-- footerFormat -->") > -1) {
301                             while ((line = in.readLine()) != null) {
302
303                                 if (line.indexOf("<!-- /footerFormat -->") > -1) {
304                                     break;
305                                 }
306                                 footerFormat.append(" ");
307                                 footerFormat.append(line);
308                                 footerFormat.append(CofaxUtil.NEW_LINE);
309                             }
310
311                             footerFormatStr = footerFormat.toString();
312                         }
313
314                         // break from reading in a packageTag
315
if ((line.indexOf("<!-- /packageTag -->") > -1) || (line.indexOf("<!-- /glossaryTag -->") > -1)) {
316                             break;
317                         }
318                     }
319
320                     // get package data from database
321
db = page.getDataStore();
322                     if (db != null && db.isConnected()) {
323                         try {
324                             tagStatement = db.getPackageTag(tag, glossary, servingPage, servingClient);
325                             packageRows = db.getPackageData(nameSpace, tagStatement, servingPage, servingClient);
326                         } catch (Exception JavaDoc e) {
327                             page.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
328                             page.setErrorMsg("Error in datastore: " + db.getLastError());
329                             return false;
330                         } finally {
331                             page.disconnectDataStore();
332                         }
333                     } else {
334                         page.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
335                         String JavaDoc errMsg = "No database connection available.";
336                         if (db != null) {
337                             errMsg = errMsg + db.getLastError();
338                         }
339                         page.setErrorMsg(errMsg);
340                         return false;
341                     }
342
343                     if (packageRows == null) {
344                         page.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
345                         page.setErrorMsg(db.getLastError());
346                         return false;
347                     }
348
349                     glossary.put(nameSpace + ":total", Integer.toString(packageRows.size()));
350
351                     /*
352                      * Process magic packageTag params. RETURN404,
353                      * SHOWPACKAGETAG, SHOWGLOSSARY, STARTROW, NUMROWS
354                      */

355                     // SHOWPACKAGE - Appends database information about
356
// the tag executed. Useful for debugging
357
if (glossary.containsKey(nameSpace + ":SHOWPACKAGETAG")) {
358                         if (glossary.get(nameSpace + ":SHOWPACKAGETAG").toString().equals("true")) {
359                             parsedTemplate.append(CofaxUtil.XHTML_NEW_LINE);
360                             parsedTemplate.append("Tag Name: ");
361                             parsedTemplate.append(tag);
362                             parsedTemplate.append(CofaxUtil.XHTML_NEW_LINE);
363                             parsedTemplate.append("packageTag returned: ");
364                             parsedTemplate.append(tagStatement);
365                             parsedTemplate.append(CofaxUtil.XHTML_NEW_LINE);
366                             parsedTemplate.append("Rows Returned: ");
367                             parsedTemplate.append(packageRows.size());
368                             parsedTemplate.append(CofaxUtil.XHTML_NEW_LINE);
369                             parsedTemplate.append("Errors, if any: ");
370                             parsedTemplate.append(db.getLastError());
371                             parsedTemplate.append(CofaxUtil.XHTML_NEW_LINE);
372                         }
373                         glossary.remove(nameSpace + ":SHOWPACKAGETAG");
374                     }
375
376                     // RETURN404 - returns a 404 if results are blank
377
if (packageRows.size() == 0) {
378                         if (glossary.containsKey(nameSpace + ":RETURN404")) {
379                             // TO DO: Get error codes from template or config
380
// file
381
page.setStatus(HttpServletResponse.SC_NOT_FOUND);
382                             page.setErrorMsg("Query returned no results.");
383                             return false;
384                         }
385                     }
386
387                     // ADDTOGLOSSARY - Add a row of these values to the glossary
388
count = 0;
389                     if (packageRows.size() > 0) {
390                         if (glossary.containsKey(nameSpace + ":ADDTOGLOSSARY") || addToGlossary == true) {
391                             rows = packageRows.iterator();
392                             while (rows.hasNext()) {
393                                 // if multiple rows are returned, take the first
394
// one
395
if (count++ == 1) {
396                                     row = (HashMap) rows.next();
397                                     for (i = row.keySet().iterator(); i.hasNext();) {
398                                         key = i.next().toString();
399                                         value = row.get(key).toString();
400                                         glossary.put(key + "", value + "");
401                                     }
402                                     break;
403                                 }
404                             }
405                             glossary.remove(nameSpace + ":ADDTOGLOSSARY");
406                         }
407                     }
408
409                     // SHOWGLOSSARY - Print out current glossary
410
// been sent as a parameter
411
if (glossary.containsKey(nameSpace + ":SHOWGLOSSARY")) {
412                         if (glossary.get(nameSpace + ":SHOWGLOSSARY").toString().equals("true")) {
413                             parsedTemplate.append("-- being PRINTING GLOSSARY --");
414                             parsedTemplate.append(CofaxUtil.XHTML_NEW_LINE);
415                             for (i = glossary.keySet().iterator(); i.hasNext();) {
416                                 key = i.next().toString();
417                                 value = glossary.get(key).toString();
418                                 parsedTemplate.append(key + " = " + value);
419                                 parsedTemplate.append(CofaxUtil.XHTML_NEW_LINE);
420
421                             }
422                             parsedTemplate.append("-- end PRINTING GLOSSARY --");
423                             parsedTemplate.append(CofaxUtil.XHTML_NEW_LINE);
424                         }
425                         glossary.remove(nameSpace + ":SHOWGLOSSARY");
426                     }
427
428                     // STARTROW - the row to begin to parse rows returned.
429
// The default is 0 and returns all
430
startRow = 0;
431                     if (glossary.containsKey(nameSpace + ":STARTROW")) {
432                         startRow = new Integer JavaDoc(glossary.get(nameSpace + ":STARTROW").toString()).intValue();
433                         glossary.remove(nameSpace + ":STARTROW");
434                     }
435
436                     // NUMROWS - The number of rows to parse.
437
// The default is 0 and returns all.
438
numRows = 0;
439                     if (glossary.containsKey(nameSpace + ":NUMROWS")) {
440                         numRows = new Integer JavaDoc(glossary.get(nameSpace + ":NUMROWS").toString()).intValue();
441                         glossary.remove(nameSpace + ":NUMROWS");
442                     }
443
444                     // Parse format code with package data and put into template
445
packageResults = doPackage(packageRows, displayFormatStr, noArticlesStr, headerFormatStr, footerFormatStr, startRow, numRows);
446
447                     parsedTemplate.append(packageResults);
448                     parsedTemplate.append(CofaxUtil.NEW_LINE);
449
450                 } else if (line.indexOf("<!-- header name") > -1) {
451                     /*
452                      * read template coded headers for the entire template <!--
453                      * header name="headerName" value="headerValue" -->
454                      */

455                     headerLoc = line.indexOf("<!-- header name");
456                     firstHeaderQuote = line.indexOf('"', headerLoc);
457                     secondHeaderQuote = line.indexOf('"', firstHeaderQuote + 1);
458                     headerName = line.substring(firstHeaderQuote + 1, secondHeaderQuote);
459                     valLoc = line.indexOf("value", secondHeaderQuote + 1);
460                     thirdHeaderQuote = line.indexOf('"', valLoc);
461                     fourthHeaderQuote = line.indexOf('"', thirdHeaderQuote + 1);
462                     headerValue = line.substring(thirdHeaderQuote + 1, fourthHeaderQuote);
463                     page.putHeader(headerName, headerValue);
464                 } else {
465                     // For other junk just append..
466
parsedTemplate.append(line);
467                     parsedTemplate.append(CofaxUtil.NEW_LINE);
468
469                 }
470             }
471         } catch (Exception JavaDoc e) {
472             page.setStatus(HttpServletResponse.SC_NOT_FOUND);
473             page.setErrorMsg("Package tag processing had an error: " + e.toString());
474             System.out.print("\nTRACE:\n");
475             e.printStackTrace();
476             return false;
477         }
478         /*
479          * parse the glossary with the template in one pass and fill in the
480          * page's StringBuffer
481          */

482         page.append(applyGlossary(parsedTemplate.toString(), glossary));
483
484         // page.append(parsedTemplate.toString());
485
// If this did not go well, set an error code
486
if (page.getContentsLength() == 0) {
487             // TO DO: Get error codes from template or config file
488
page.setStatus(HttpServletResponse.SC_NOT_FOUND);
489             page.setErrorMsg("Package tag processing had an error: Parsed template length was 0");
490             return false;
491         }
492         return true;
493     }
494
495     /**
496      * Processes template and returns a string.
497      *
498      * @param template
499      * Description of the Parameter
500      * @param glossary
501      * Description of the Parameter
502      * @return Description of the Return Value
503      */

504     public final String JavaDoc applyTemplate(StringBuffer JavaDoc template, HashMap glossary) {
505
506         // We will be building and returning parsedTemplate
507
StringBuffer JavaDoc parsedTemplate = new StringBuffer JavaDoc(CofaxUtil.COMMON_DATA_SIZE);
508
509         parsedTemplate.append(applyGlossary(template.toString(), glossary));
510
511         return parsedTemplate.toString();
512     }
513
514     /**
515      * Applies a HashMap, to a piece of text, doing search and replaces for
516      * displayTags.
517      *
518      * @param parseTemplate
519      * Description of the Parameter
520      * @param glossary
521      * Description of the Parameter
522      * @return Description of the Return Value
523      */

524     private final static String JavaDoc applyGlossaryCaseInsensitive(String JavaDoc parseTemplate, HashMap glossary) {
525
526         // NOTE that calls to parseTemplate.indexOf(String)
527
// will throw a NullPointerExcpetion
528
// if parseTemplate is null. It should not be.
529

530         for (Iterator i = glossary.keySet().iterator(); i.hasNext();) {
531             String JavaDoc tag = (String JavaDoc) i.next();
532             String JavaDoc value = glossary.get(tag).toString();
533             String JavaDoc tagToSearchFor = "";
534             int numTimes = 0;
535
536             // decide whether the value is blank and set a boolean.
537
boolean gotValue = true;
538             if ((value == null) || (value.equals("") || (value.equals("null")))) {
539                 gotValue = false;
540                 value = "";
541             }
542
543             // Uppercase tag header, display, footer Format of PackageTags
544

545             tag = tag.toUpperCase();
546
547             String JavaDoc parseTemplateUpperCase = parseTemplate.toUpperCase();
548
549             /*
550              * Parse for standard comments syntax. runs the same whether a value
551              * is present or not. <!-- getSection:headline -->headline here <!--
552              * /getSection:headline -->
553              */

554             tagToSearchFor = "<!-- " + tag + " -->";
555             int firstCommentLoc = parseTemplateUpperCase.indexOf(tagToSearchFor);
556             while (firstCommentLoc > -1) {
557                 int lastCommentLoc = parseTemplateUpperCase.indexOf("<!-- /" + tag + " -->", firstCommentLoc);
558                 if ((firstCommentLoc > -1) && (lastCommentLoc > -1)) {
559                     StringBuffer JavaDoc newText = new StringBuffer JavaDoc();
560                     newText.append(parseTemplate.substring(0, firstCommentLoc));
561                     newText.append("<!-- ");
562                     newText.append(tag);
563                     newText.append(" -->");
564                     newText.append(value);
565                     newText.append(parseTemplate.substring(lastCommentLoc));
566                     parseTemplate = newText.toString();
567                     parseTemplateUpperCase = parseTemplate.toUpperCase();
568                 }
569                 firstCommentLoc = parseTemplateUpperCase.indexOf("<!-- " + tag + " -->", lastCommentLoc);
570             }
571
572             /*
573              * Parse standard backticks syntax `getSection:headline`
574              */

575             tagToSearchFor = "`" + tag + "`";
576             int firstTickLoc = parseTemplateUpperCase.indexOf(tagToSearchFor);
577             while (firstTickLoc > -1) {
578                 int lastTickLoc = firstTickLoc + tagToSearchFor.length();
579                 if ((firstTickLoc > -1) && (lastTickLoc > -1)) {
580                     StringBuffer JavaDoc newText = new StringBuffer JavaDoc();
581                     newText.append(parseTemplate.substring(0, firstTickLoc));
582                     newText.append(value);
583                     newText.append(parseTemplate.substring(firstTickLoc + tagToSearchFor.length()));
584                     parseTemplate = newText.toString();
585                     parseTemplateUpperCase = parseTemplate.toUpperCase();
586                 }
587                 firstTickLoc = parseTemplateUpperCase.indexOf(tagToSearchFor, lastTickLoc);
588             }
589             // end while with backstick
590

591             /*
592              * Parse for stripline comments syntax. this would be the equivalent
593              * of: <h2><!-- getSection:headline stripLine="true" -->headline
594              * here<!-- /getSection:headline --></h2>
595              */

596             tagToSearchFor = "<!-- " + tag + " STRIPLINE=\"TRUE\" -->";
597             int firstStripCommentLoc = parseTemplateUpperCase.indexOf(tagToSearchFor);
598             while (firstStripCommentLoc > -1) {
599                 int firstNewLineLoc = parseTemplateUpperCase.lastIndexOf('\n', firstStripCommentLoc);
600                 int lastCommentLoc = parseTemplateUpperCase.indexOf("<!-- /" + tag + " -->", firstStripCommentLoc);
601                 int lastNewLineLoc = parseTemplateUpperCase.indexOf('\n', lastCommentLoc);
602                 if ((firstStripCommentLoc > -1) && (lastCommentLoc > -1) && (firstNewLineLoc > -1) && (lastNewLineLoc > -1)) {
603                     StringBuffer JavaDoc newText = new StringBuffer JavaDoc();
604                     newText.append(parseTemplate.substring(0, firstNewLineLoc));
605                     if (gotValue) {
606                         newText.append(parseTemplate.substring(firstNewLineLoc, firstStripCommentLoc));
607                         newText.append("<!-- ");
608                         newText.append(tag);
609                         newText.append(" stripLine=\"true\" -->");
610                         newText.append(value);
611                         newText.append(parseTemplate.substring(lastCommentLoc));
612                     } else {
613                         newText.append(parseTemplate.substring(lastNewLineLoc));
614                     }
615
616                     parseTemplate = newText.toString();
617                     parseTemplateUpperCase = parseTemplate.toUpperCase();
618
619                 }
620                 firstStripCommentLoc = parseTemplateUpperCase.indexOf(tagToSearchFor, lastCommentLoc);
621             }
622             // end while with backstick
623

624             /*
625              * Parse for stripline backticks syntax. this would be the
626              * equivalent of: <h2>`getSection:headline stripLine=true`</h2>
627              */

628             tagToSearchFor = "`" + tag + " STRIPLINE=TRUE`";
629             int firstStripTickLoc = parseTemplateUpperCase.indexOf(tagToSearchFor);
630             while (firstStripTickLoc > -1) {
631                 int firstNewLineLoc = parseTemplateUpperCase.lastIndexOf('\n', firstStripTickLoc);
632                 int lastStripTickLoc = firstStripTickLoc + tagToSearchFor.length();
633                 int lastNewLineLoc = parseTemplateUpperCase.indexOf('\n', lastStripTickLoc);
634
635                 if ((firstStripTickLoc > -1) && (lastStripTickLoc > -1) && (firstNewLineLoc > -1) && (lastNewLineLoc > -1)) {
636                     StringBuffer JavaDoc newText = new StringBuffer JavaDoc();
637                     newText.append(parseTemplate.substring(0, firstNewLineLoc));
638                     if (gotValue) {
639                         newText.append(parseTemplate.substring(firstNewLineLoc, firstStripTickLoc));
640                         newText.append(value);
641                         newText.append(parseTemplate.substring(lastStripTickLoc));
642                     } else {
643                         newText.append(parseTemplate.substring(lastNewLineLoc));
644                     }
645
646                     parseTemplate = newText.toString();
647                     parseTemplateUpperCase = parseTemplate.toUpperCase();
648
649                 }
650                 firstStripTickLoc = parseTemplateUpperCase.indexOf(tagToSearchFor, lastStripTickLoc);
651             }
652             // end while with backstick
653

654         }
655
656         return parseTemplate;
657     }
658
659     // end applyGlossary
660

661     /**
662      * Applies a HashMap, to a piece of text, doing search and replaces for
663      * displayTags.
664      *
665      * @param parseTemplate
666      * Description of the Parameter
667      * @param glossary
668      * Description of the Parameter
669      * @return Description of the Return Value
670      */

671     private final static String JavaDoc applyGlossary(String JavaDoc parseTemplate, HashMap glossary) {
672
673         // NOTE that calls to parseTemplate.indexOf(String)
674
// will throw a NullPointerExcpetion
675
// if parseTemplate is null. It should not be.
676

677         boolean gotValue = true;
678
679         int numTimes = 0;
680         int firstCommentLoc = 0;
681         int lastCommentLoc = 0;
682         int firstTickLoc = 0;
683         int lastTickLoc = 0;
684         int firstStripCommentLoc = 0;
685         int firstNewLineLoc = 0;
686         int lastNewLineLoc = 0;
687         int firstStripTickLoc = 0;
688         int lastStripTickLoc = 0;
689
690         String JavaDoc tag;
691         String JavaDoc value;
692         String JavaDoc tagToSearchFor = "";
693
694         StringBuffer JavaDoc newText = new StringBuffer JavaDoc();
695
696         for (Iterator i = glossary.keySet().iterator(); i.hasNext();) {
697             tag = (String JavaDoc) i.next();
698             value = glossary.get(tag).toString();
699             tagToSearchFor = "";
700             numTimes = 0;
701
702             // decide whether the value is blank and set a boolean.
703
gotValue = true;
704             if ((value == null) || (value.equals("") || (value.equals("null")))) {
705                 gotValue = false;
706                 value = "";
707             }
708
709             /*
710              * Parse for standard comments syntax. runs the same whether a value
711              * is present or not. <!-- getSection:headline -->headline here <!--
712              * /getSection:headline -->
713              */

714             tagToSearchFor = "<!-- " + tag + " -->";
715             firstCommentLoc = parseTemplate.indexOf(tagToSearchFor);
716             while (firstCommentLoc > -1) {
717                 lastCommentLoc = parseTemplate.indexOf("<!-- /" + tag + " -->", firstCommentLoc);
718                 if ((firstCommentLoc > -1) && (lastCommentLoc > -1)) {
719                     newText.setLength(0);
720                     newText.append(parseTemplate.substring(0, firstCommentLoc));
721                     newText.append("<!-- ");
722                     newText.append(tag);
723                     newText.append(" -->");
724                     newText.append(value);
725                     newText.append(parseTemplate.substring(lastCommentLoc));
726                     parseTemplate = newText.toString();
727                 } else if (lastCommentLoc == -1) {
728                     lastCommentLoc = firstCommentLoc + 1;
729                 }
730                 firstCommentLoc = parseTemplate.indexOf("<!-- " + tag + " -->", lastCommentLoc);
731             }
732
733             /*
734              * Parse standard backticks syntax `getSection:headline`
735              */

736             tagToSearchFor = "`" + tag + "`";
737             firstTickLoc = parseTemplate.indexOf(tagToSearchFor);
738             while (firstTickLoc > -1) {
739                 lastTickLoc = firstTickLoc + tagToSearchFor.length();
740                 if ((firstTickLoc > -1) && (lastTickLoc > -1)) {
741                     newText.setLength(0);
742                     newText.append(parseTemplate.substring(0, firstTickLoc));
743                     newText.append(value);
744                     newText.append(parseTemplate.substring(firstTickLoc + tagToSearchFor.length()));
745                     parseTemplate = newText.toString();
746
747                 } else if (lastTickLoc == -1) {
748                     lastTickLoc = firstTickLoc + 1;
749                 }
750                 firstTickLoc = parseTemplate.indexOf(tagToSearchFor, lastTickLoc);
751             }
752             // end while with backstick
753

754             /*
755              * Parse for stripline comments syntax. this would be the equivalent
756              * of: <h2><!-- getSection:headline stripLine="true" -->headline
757              * here<!-- /getSection:headline --></h2>
758              */

759             tagToSearchFor = "<!-- " + tag + " stripLine=\"true\" -->";
760             firstStripCommentLoc = parseTemplate.indexOf(tagToSearchFor);
761             while (firstStripCommentLoc > -1) {
762                 firstNewLineLoc = parseTemplate.lastIndexOf('\n', firstStripCommentLoc);
763                 lastCommentLoc = parseTemplate.indexOf("<!-- /" + tag + " -->", firstStripCommentLoc);
764                 lastNewLineLoc = parseTemplate.indexOf('\n', lastCommentLoc);
765                 if ((firstStripCommentLoc > -1) && (lastCommentLoc > -1) && (firstNewLineLoc > -1) && (lastNewLineLoc > -1)) {
766                     newText.setLength(0);
767                     newText.append(parseTemplate.substring(0, firstNewLineLoc));
768                     if (gotValue) {
769                         newText.append(parseTemplate.substring(firstNewLineLoc, firstStripCommentLoc));
770                         newText.append("<!-- ");
771                         newText.append(tag);
772                         newText.append(" stripLine=\"true\" -->");
773                         newText.append(value);
774                         newText.append(parseTemplate.substring(lastCommentLoc));
775                     } else {
776                         newText.append(parseTemplate.substring(lastNewLineLoc));
777                     }
778
779                     parseTemplate = newText.toString();
780
781                 } else if (lastCommentLoc == -1) {
782                     lastCommentLoc = firstStripCommentLoc + 1;
783                 }
784                 firstStripCommentLoc = parseTemplate.indexOf(tagToSearchFor, lastCommentLoc);
785             }
786             // end while with backstick
787

788             /*
789              * Parse for stripline backticks syntax. this would be the
790              * equivalent of: <h2>`getSection:headline stripLine=true`</h2>
791              */

792             tagToSearchFor = "`" + tag + " stripLine=true`";
793             firstStripTickLoc = parseTemplate.indexOf(tagToSearchFor);
794             while (firstStripTickLoc > -1) {
795                 firstNewLineLoc = parseTemplate.lastIndexOf('\n', firstStripTickLoc);
796                 lastStripTickLoc = firstStripTickLoc + tagToSearchFor.length();
797                 lastNewLineLoc = parseTemplate.indexOf('\n', lastStripTickLoc);
798
799                 if ((firstStripTickLoc > -1) && (lastStripTickLoc > -1) && (firstNewLineLoc > -1) && (lastNewLineLoc > -1)) {
800                     newText.setLength(0);
801                     newText.append(parseTemplate.substring(0, firstNewLineLoc));
802                     if (gotValue) {
803                         newText.append(parseTemplate.substring(firstNewLineLoc, firstStripTickLoc));
804                         newText.append(value);
805                         newText.append(parseTemplate.substring(lastStripTickLoc));
806                     } else {
807                         newText.append(parseTemplate.substring(lastNewLineLoc));
808                     }
809
810                     parseTemplate = newText.toString();
811
812                 } else if (lastStripTickLoc == -1) {
813                     lastStripTickLoc = firstStripTickLoc + 1;
814                 }
815                 firstStripTickLoc = parseTemplate.indexOf(tagToSearchFor, lastStripTickLoc);
816             }
817             // end while with backstick
818

819         }
820         return parseTemplate;
821     }
822
823     // end applyGlossary
824

825     /**
826      * Adds a packageTag parameter to the glossary space
827      *
828      * @param glossary
829      * The feature to be added to the ParamToGlossary attribute
830      * @param nameSpace
831      * The feature to be added to the ParamToGlossary attribute
832      * @param line
833      * The feature to be added to the ParamToGlossary attribute
834      * @return Description of the Return Value
835      */

836     private final boolean addParamToGlossary(HashMap glossary, String JavaDoc nameSpace, String JavaDoc line) {
837
838         int paramLoc = line.indexOf("<!-- param name");
839         int firstParamQuote = line.indexOf('"', paramLoc);
840         int secondParamQuote = line.indexOf('"', firstParamQuote + 1);
841         String JavaDoc paramName = line.substring(firstParamQuote + 1, secondParamQuote);
842
843         int valLoc = line.indexOf("value", secondParamQuote + 1);
844         int thirdParamQuote = line.indexOf('"', valLoc);
845         int fourthParamQuote = line.indexOf('"', thirdParamQuote + 1);
846         String JavaDoc paramValue = line.substring(thirdParamQuote + 1, fourthParamQuote);
847
848         // If the param is not already namespaced, then
849
// we apply the default namespace (the name of this tag)
850
// to it.
851
if (!(paramName.indexOf(':') > -1)) {
852             paramName = nameSpace + ":" + paramName;
853         }
854
855         // Get values from glossary if present
856
// if (value.charAt('`')) { // this is faster
857
if (paramValue.startsWith("`") && paramValue.endsWith("`")) {
858
859             String JavaDoc valueOnly = paramValue.substring(1, paramValue.length() - 1);
860
861             if (glossary.containsKey(valueOnly)) {
862                 paramValue = (String JavaDoc) glossary.get(valueOnly);
863             } else {
864                 // Attempt to lookup the paramName from the glossary if it
865
// exists.
866
String JavaDoc valueToOverride = "";
867                 if (glossary.containsKey(paramName)) {
868                     valueToOverride = (String JavaDoc) glossary.get(paramName);
869                 }
870                 paramValue = processParam(valueToOverride, valueOnly);
871             }
872         }
873
874         glossary.put(paramName, paramValue);
875
876         return true;
877     }
878
879     /**
880      * Parses formats with package data. Returns parsed result or
881      * noArticlesMessage if no package data was sent.
882      *
883      * @param packageRows
884      * Description of the Parameter
885      * @param displayFormatStr
886      * Description of the Parameter
887      * @param noArticlesMessage
888      * Description of the Parameter
889      * @param headerRowStr
890      * Description of the Parameter
891      * @param footerRowStr
892      * Description of the Parameter
893      * @param startRow
894      * Description of the Parameter
895      * @param numRows
896      * Description of the Parameter
897      * @return Description of the Return Value
898      */

899     private final String JavaDoc doPackage(List packageRows, String JavaDoc displayFormatStr, String JavaDoc noArticlesMessage, String JavaDoc headerRowStr, String JavaDoc footerRowStr, int startRow,
900             int numRows) {
901
902         StringBuffer JavaDoc packageResults = new StringBuffer JavaDoc(CofaxUtil.COMMON_DATA_SIZE);
903
904         StringBuffer JavaDoc packageResultsHeader = new StringBuffer JavaDoc(CofaxUtil.COMMON_DATA_SIZE);
905
906         StringBuffer JavaDoc packageResultsFooter = new StringBuffer JavaDoc(CofaxUtil.COMMON_DATA_SIZE);
907
908         // if rows were retrieved, loop through and parse with format code
909
if (packageRows != null && packageRows.size() > 0) {
910
911             Iterator lines = packageRows.iterator();
912             HashMap packageRow;
913             int rowNumber = 0;
914             int rowsProcessed = 0;
915             boolean getOneRow = false;
916             HashMap packageRowOne = new HashMap();
917
918             while (lines.hasNext()) {
919                 packageRow = (HashMap) lines.next();
920                 rowNumber++;
921
922                 packageRowOne = (HashMap) packageRow;
923                 // use for header & footer stuff
924
getOneRow = true;
925
926                 if (rowNumber >= startRow) {
927
928                     if (numRows > 0) {
929                         rowsProcessed++;
930                         if (rowsProcessed <= numRows) {
931                             packageResults.append(applyGlossary(displayFormatStr, packageRow));
932                             packageResults.append(CofaxUtil.NEW_LINE);
933                         }
934                     } else {
935                         rowsProcessed++;
936                         packageResults.append(applyGlossary(displayFormatStr, packageRow));
937                         packageResults.append(CofaxUtil.NEW_LINE);
938
939                     }
940                 }
941             }
942             // end While
943

944             if (getOneRow) {
945                 packageResultsHeader.append(applyGlossary(headerRowStr, packageRowOne));
946                 packageResultsHeader.append(CofaxUtil.NEW_LINE);
947
948                 packageResultsFooter.append(applyGlossary(footerRowStr, packageRowOne));
949                 packageResultsFooter.append(CofaxUtil.NEW_LINE);
950
951             }
952         } else {
953             // if articles were retrieved, loop through and parse with format
954
// code
955
return noArticlesMessage;
956         }
957
958         packageResults = packageResultsHeader.append(packageResults);
959         packageResults = packageResults.append(packageResultsFooter);
960
961         return packageResults.toString();
962     }
963
964     /**
965      * Process param method calls
966      *
967      * @param paramName
968      * Description of the Parameter
969      * @param paramToProcess
970      * Description of the Parameter
971      * @return Description of the Return Value
972      */

973     private final String JavaDoc processParam(String JavaDoc paramName, String JavaDoc paramToProcess) {
974
975         // dateadd() method
976
if (paramToProcess.startsWith("dateadd(") && paramToProcess.endsWith(")")) {
977
978             // get the datepart to manipulate
979
int firstParamBegin = paramToProcess.indexOf('(');
980             int firstParamEnd = paramToProcess.indexOf(',', firstParamBegin);
981             String JavaDoc datePartParam = paramToProcess.substring(firstParamBegin + 1, firstParamEnd);
982             // get the number to add/subtract
983
int secondParamEnd = paramToProcess.indexOf(')');
984             String JavaDoc num = paramToProcess.substring(firstParamEnd + 1, secondParamEnd);
985
986             try {
987                 // parse the number into an integer
988

989                 int numParam = Integer.parseInt(num);
990
991                 if ((numParam != 0) && (!datePartParam.equals(""))) {
992
993                     GregorianCalendar cal = new GregorianCalendar();
994                     try {
995
996                         SimpleDateFormat JavaDoc df = new SimpleDateFormat JavaDoc("yyyy/MM/dd");
997                         Date paramDate = df.parse(paramName);
998
999                         cal.setTime(paramDate);
1000                        if (datePartParam.equals("YEAR")) {
1001                            cal.roll(Calendar.YEAR, numParam);
1002                            // 2000
1003
} else if (datePartParam.equals("MONTH")) {
1004                            cal.roll(Calendar.MONTH, numParam);
1005                            // 10
1006
} else if (datePartParam.equals("DAY")) {
1007                            cal.roll(Calendar.DATE, numParam);
1008                            // 4
1009
}
1010
1011                        String JavaDoc year = new Integer JavaDoc(cal.get(Calendar.YEAR)).toString();
1012                        String JavaDoc month = new Integer JavaDoc(cal.get(Calendar.MONTH) + 1).toString();
1013                        String JavaDoc day = new Integer JavaDoc(cal.get(Calendar.DATE)).toString();
1014
1015                        if (month.length() < 2) {
1016                            month = "0" + month;
1017                        }
1018
1019                        if (day.length() < 2) {
1020                            day = "0" + day;
1021                        }
1022
1023                        paramToProcess = year + "/" + month + "/" + day;
1024
1025                    } catch (java.text.ParseException JavaDoc e) {
1026                        // Bad date format
1027
// TO DO: Return a meaningful error to the template
1028
// designer.
1029
}
1030                }
1031            } catch (NumberFormatException JavaDoc e) {
1032                // Bad number format.
1033
// TO DO: Return a meaningful error to the template designer.
1034
}
1035        }
1036
1037        return paramToProcess;
1038    }
1039
1040}
1041
Popular Tags