001: /*
002: * Created on Jan 31, 2005
003: *
004: */
005: package net.sf.thingamablog.generator;
006:
007: import java.io.IOException;
008: import java.io.OutputStream;
009: import java.io.OutputStreamWriter;
010: import java.io.PrintWriter;
011: import java.io.Writer;
012: import java.util.Iterator;
013: import java.util.List;
014: import java.util.Locale;
015: import java.util.Vector;
016:
017: import net.sf.thingamablog.blog.ArchiveRange;
018: import net.sf.thingamablog.blog.TBWeblog;
019:
020: /**
021: * @author Bob Tantlinger
022: *
023: */
024: public class PageGenerator {
025: /** Constant for the RSS feed */
026: public static final int RSS_PAGE = -1;
027: /** Constant for the front page */
028: public static final int FRONT_PAGE = -2;
029: /** Constant for the archive index page */
030: public static final int INDEX_PAGE = -3;
031:
032: private Vector customTags = new Vector();
033: private String charset = "UTF-8";//default charset
034:
035: //default container attributes
036: private String archiveRangeFormat = "MMMM, dd yyyy";
037: private boolean spanArcRange = true;
038:
039: private String dateFormat = archiveRangeFormat;
040: private String timeFormat = "h:mm a";
041:
042: private int frontPageLimit = 10;
043: private boolean isLimitFrontPage = true;
044:
045: private int categoryPageLimit = 20;
046: private boolean isLimitCategoryPage = true;
047:
048: private boolean isFrontPageAscending;
049: private boolean isCategoryPageAscending;
050: private boolean isArchivePageAscending;
051:
052: private boolean isLimitRssEntry = true;
053:
054: private TemplateProcessor pageBuilder = new TemplateProcessor();
055:
056: public PageGenerator() {
057:
058: }
059:
060: private void writePage(BlogPageContainer bpc, String template,
061: OutputStream out) throws IOException {
062: writePage(bpc, null, template, out);
063: }
064:
065: private void writePage(BlogPageContainer bpc,
066: BlogEntryContainer bec, String template, OutputStream out)
067: throws IOException {
068: for (int i = 0; i < customTags.size(); i++)
069: bpc.addCustomTag((CustomTag) customTags.elementAt(i));
070:
071: Writer writer = new OutputStreamWriter(out, charset);
072: PrintWriter pw = new PrintWriter(writer);
073:
074: String rootName = BlogPageContainer.NAME;
075: template = "<" + rootName + ">" + template + "</" + rootName
076: + ">";
077: String text = pageBuilder.processTemplate(template, bpc);
078:
079: /*
080: * Writing all the entries for a page to a string
081: * would be memeory-intensive if there are a lot of entries.
082: * Thus, it seems safer and more effecient to write the
083: * entries directly to disk.
084: */
085: if (bec != null) {
086: List entryTmpls = pageBuilder.parseContainers(text, bec);
087: if (entryTmpls.size() == 0)//no entry containers found
088: {
089: pw.write(text);
090: } else {
091: Iterator it = entryTmpls.iterator();
092: int pos = 0;
093: while (it.hasNext()) {
094: String ec = it.next().toString();
095:
096: int ecPos = text.indexOf(ec, pos);
097: String part = text.substring(pos, ecPos);
098: writer.write(part);
099: pageBuilder.writeContainer(ec, bec, writer);
100: pos = ecPos + ec.length();
101: }
102:
103: writer.write(text.substring(pos, text.length()));
104: }
105: } else {
106: pw.write(text);
107: }
108:
109: writer.close();
110: pw.close();
111: }
112:
113: /**
114: * Generate a category page
115: *
116: * @param blog The weblog from which the page will be generated
117: * @param cat The category
118: * @param out The OutputStream to write the page to
119: * @param template The template
120: */
121: public void generatePage(TBWeblog blog, String cat,
122: OutputStream out, String template) throws IOException {
123: BlogPageContainer bpc = new BlogPageContainer(blog, cat,
124: charset);
125: BlogEntryContainer bec = new BlogEntryContainer(blog, cat);
126: bec.setDefaultSortOrder(isCategoryPageAscending);
127: bec.setDefaultDateFormat(dateFormat);
128: bec.setDefaultTimeFormat(timeFormat);
129: bec.setDefaultIsLimit(isLimitCategoryPage);
130: bec.setDefaultLimitBy(categoryPageLimit);
131: bpc.addContainer(new CalendarContainer(blog, cat));
132: bpc.addContainer(new CategoryListContainer(blog));
133: bpc.addContainer(new ArchiveYearsContainer(blog,
134: archiveRangeFormat, spanArcRange));
135: bpc.addContainer(new ArchiveListContainer(blog,
136: archiveRangeFormat, spanArcRange));
137: bpc.addContainer(new NextPreviousContainer(blog, cat,
138: NextPreviousContainer.NEXT));
139: bpc.addContainer(new NextPreviousContainer(blog, cat,
140: NextPreviousContainer.PREV));
141: bpc.addContainer(new IncludeContainer());
142: //bpc.addContainer(bec);
143: //writePage(bpc, template, out);
144: writePage(bpc, bec, template, out);
145: }
146:
147: /**
148: * Generate an archive page
149: *
150: * @param blog The weblog
151: * @param arc The archive of the page
152: * @param out The OutputStream to write the page to
153: * @param template The template
154: */
155: public void generatePage(TBWeblog blog, ArchiveRange arc,
156: OutputStream out, String template) throws IOException {
157: BlogPageContainer bpc = new BlogPageContainer(blog,
158: formatArcRange(arc, blog.getLocale()), charset);
159: BlogEntryContainer bec = new BlogEntryContainer(blog, arc);
160: bec.setDefaultSortOrder(isArchivePageAscending);
161: bec.setDefaultDateFormat(dateFormat);
162: bec.setDefaultTimeFormat(timeFormat);
163: bpc.addContainer(new CalendarContainer(blog, arc));
164: bpc.addContainer(new CategoryListContainer(blog));
165: bpc.addContainer(new ArchiveYearsContainer(blog,
166: archiveRangeFormat, spanArcRange));
167: bpc.addContainer(new ArchiveListContainer(blog,
168: archiveRangeFormat, spanArcRange));
169: bpc.addContainer(new NextPreviousContainer(blog, arc,
170: NextPreviousContainer.NEXT));
171: bpc.addContainer(new NextPreviousContainer(blog, arc,
172: NextPreviousContainer.PREV));
173: bpc.addContainer(new IncludeContainer());
174:
175: //bpc.addContainer(bec);
176: //writePage(bpc, template, out);
177: writePage(bpc, bec, template, out);
178: }
179:
180: private String formatArcRange(ArchiveRange ar, Locale locale) {
181: java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(
182: archiveRangeFormat, locale);
183: String s = sdf.format(ar.getStartDate());
184: if (spanArcRange)
185: s += " - " + sdf.format(ar.getExpirationDate());
186:
187: return s;
188: }
189:
190: public void generatePage(TBWeblog blog, long id, OutputStream out,
191: String template) throws IOException {
192: String title;
193: try {
194: title = blog.getEntry(id).getTitle();
195: } catch (Exception ex) {
196: title = blog.getTitle();
197: }
198: BlogPageContainer bpc = new BlogPageContainer(blog, title,
199: charset);
200: BlogEntryContainer container = new BlogEntryContainer(blog, id);
201: container.setDefaultDateFormat(dateFormat);
202: container.setDefaultTimeFormat(timeFormat);
203: //container.setDefaultIsLimit(isLimitFrontPage);
204: //container.setDefaultLimitBy(frontPageLimit);
205: //container.setDefaultSortOrder(isFrontPageAscending);
206: //bpc.addContainer(container);
207: bpc.addContainer(new CategoryListContainer(blog));
208: bpc.addContainer(new ArchiveYearsContainer(blog,
209: archiveRangeFormat, spanArcRange));
210: bpc.addContainer(new ArchiveListContainer(blog,
211: archiveRangeFormat, spanArcRange));
212: bpc.addContainer(new NextPreviousContainer(blog, id,
213: NextPreviousContainer.NEXT));
214: bpc.addContainer(new NextPreviousContainer(blog, id,
215: NextPreviousContainer.PREV));
216: bpc.addContainer(new IncludeContainer());
217:
218: writePage(bpc, container, template, out);
219: //writePage(bpc, template, out);
220: }
221:
222: /**
223: * Generate a front page, rss feed, or archive index page
224: *
225: * @param blog The weblog
226: * @param type The type of the page: FONT_PAGE, INDEX_PAGE, RSS_PAGE
227: * @param out The OutputStream to write the page to
228: * @param template The template
229: */
230: public void generatePage(TBWeblog blog, int type, OutputStream out,
231: String template) throws IOException {
232: BlogPageContainer bpc = new BlogPageContainer(blog, blog
233: .getTitle(), charset);
234:
235: if (type == RSS_PAGE) {
236: BlogEntryContainer container = new BlogEntryContainer(blog,
237: BlogEntryContainer.RSS_PAGE);
238: container.setLimitEntryBody(isLimitRssEntry);
239: container.setDefaultIsLimit(isLimitFrontPage);
240: container.setDefaultLimitBy(frontPageLimit);
241: container.setDefaultSortOrder(false);
242: writePage(bpc, container, template, out);
243: return;
244: }
245:
246: bpc.addContainer(new CalendarContainer(blog));
247: bpc.addContainer(new CategoryListContainer(blog));
248: bpc.addContainer(new ArchiveYearsContainer(blog,
249: archiveRangeFormat, spanArcRange));
250: bpc.addContainer(new ArchiveListContainer(blog,
251: archiveRangeFormat, spanArcRange));
252: bpc.addContainer(new NextPreviousContainer(
253: NextPreviousContainer.NEXT));
254: bpc.addContainer(new NextPreviousContainer(
255: NextPreviousContainer.PREV));
256: bpc.addContainer(new IncludeContainer());
257:
258: if (type == FRONT_PAGE) {
259: BlogEntryContainer container = new BlogEntryContainer(blog,
260: BlogEntryContainer.FRONT_PAGE);
261: container.setDefaultDateFormat(dateFormat);
262: container.setDefaultTimeFormat(timeFormat);
263: container.setDefaultIsLimit(isLimitFrontPage);
264: container.setDefaultLimitBy(frontPageLimit);
265: container.setDefaultSortOrder(isFrontPageAscending);
266: writePage(bpc, container, template, out);
267: return;
268: }
269:
270: writePage(bpc, template, out);
271: }
272:
273: /**
274: * Adds a custom tag to the generator
275: *
276: * @param tag The CustomTag
277: */
278: public void addCustomTag(CustomTag tag) {
279: if (!customTags.contains(tag))
280: customTags.add(tag);
281: }
282:
283: /**
284: * Removes a custom tag from the generator
285: *
286: * @param tag The CustomTag
287: */
288: public void removeCustomTag(CustomTag tag) {
289: customTags.remove(tag);
290: }
291:
292: /**
293: * Sets all the custom tags for the generator
294: *
295: * @param tags The CustomTags
296: */
297: public void setCustomTags(CustomTag tags[]) {
298: customTags.removeAllElements();
299: for (int i = 0; i < tags.length; i++) {
300: customTags.add(tags[i]);
301: }
302: }
303:
304: /**
305: * Gets all the custom tags from the generator
306: *
307: * @return an array of CustomTags
308: */
309: public CustomTag[] getCustomTags() {
310: CustomTag tags[] = new CustomTag[customTags.size()];
311: for (int i = 0; i < tags.length; i++) {
312: tags[i] = (CustomTag) customTags.elementAt(i);
313: }
314:
315: return tags;
316: }
317:
318: /**
319: * Gets the default ArchiveRange format
320: *
321: * @return The format
322: */
323: public String getArchiveRangeFormat() {
324: return archiveRangeFormat;
325: }
326:
327: /**
328: * Gets the default category page limit
329: *
330: * @return The limit
331: */
332: public int getCategoryPageLimit() {
333: return categoryPageLimit;
334: }
335:
336: /**
337: * Gets the default date format
338: *
339: * @return The format
340: */
341: public String getDateFormat() {
342: return dateFormat;
343: }
344:
345: /**
346: * Gets the default front page limit
347: *
348: * @return The limit
349: */
350: public int getFrontPageLimit() {
351: return frontPageLimit;
352: }
353:
354: /**
355: * Indicates if entries are written in
356: * ascending order by default for archive pages
357: *
358: * @return true if ascending, false otherwise
359: */
360: public boolean isArchivePageAscending() {
361: return isArchivePageAscending;
362: }
363:
364: /**
365: * Indicates if category page entries are written
366: * in ascending order by default
367: *
368: * @return true if ascending, false otherwise
369: */
370: public boolean isCategoryPageAscending() {
371: return isCategoryPageAscending;
372: }
373:
374: /**
375: * Indicates if front page entries are written
376: * in ascending order by default
377: *
378: * @return true if ascending, false otherwise
379: */
380: public boolean isFrontPageAscending() {
381: return isFrontPageAscending;
382: }
383:
384: /**
385: * Indicates if entries on category pages should be limited by default
386: *
387: * @return true if limit, false otherwise
388: */
389: public boolean isLimitCategoryPage() {
390: return isLimitCategoryPage;
391: }
392:
393: /**
394: * Indicates if entries on the front page should be limited by default
395: *
396: * @return true if limit, false otherwise
397: */
398: public boolean isLimitFrontPage() {
399: return isLimitFrontPage;
400: }
401:
402: /**
403: * Indicates if archive list formated dates should include both dates
404: *
405: * @return true if span, false otherwise
406: */
407: public boolean isSpanArcRange() {
408: return spanArcRange;
409: }
410:
411: /**
412: * Gets the default time format
413: *
414: * @return The format
415: */
416: public String getTimeFormat() {
417: return timeFormat;
418: }
419:
420: /**
421: * Sets the default ArchiveRange format
422: *
423: * @param string The format
424: * @param span should span
425: */
426: public void setArchiveRangeFormat(String string, boolean span) {
427: archiveRangeFormat = string;
428: spanArcRange = span;
429: }
430:
431: /**
432: * Sets the default entry limit for category pages
433: *
434: * @param i The limit
435: */
436: public void setCategoryPageLimit(int i) {
437: categoryPageLimit = i;
438: }
439:
440: /**
441: * Sets the default date format
442: *
443: * @param string The format
444: */
445: public void setDateFormat(String string) {
446: dateFormat = string;
447: }
448:
449: /**
450: * Sets the default front page entry limit
451: *
452: * @param i The limit
453: */
454: public void setFrontPageLimit(int i) {
455: frontPageLimit = i;
456: }
457:
458: /**
459: * Sets the default chronological sort order of entries on archive pages
460: *
461: * @param b The sort order
462: */
463: public void setArchivePageAscending(boolean b) {
464: isArchivePageAscending = b;
465: }
466:
467: /**
468: * Sets the default chronological sort order of entries on category pages
469: *
470: * @param The sort order
471: */
472: public void setCategoryPageAscending(boolean b) {
473: isCategoryPageAscending = b;
474: }
475:
476: /**
477: * Sets the default chronological sort order of entries on the front page
478: *
479: * @param b The sort order
480: */
481: public void setFrontPageAscending(boolean b) {
482: isFrontPageAscending = b;
483: }
484:
485: /**
486: * Sets the default limit policy for category pages
487: *
488: * @param b should limit
489: */
490: public void setLimitCategoryPage(boolean b) {
491: isLimitCategoryPage = b;
492: }
493:
494: /**
495: * Sets the default limit policy for the front page
496: *
497: * @param b should limit
498: */
499: public void setLimitFrontPage(boolean b) {
500: isLimitFrontPage = b;
501: }
502:
503: /**
504: * Sets the default time format
505: *
506: * @param string The format
507: */
508: public void setTimeFormat(String string) {
509: timeFormat = string;
510: }
511:
512: /**
513: * Indicates if the body of RSS entries should be truncated by default
514: *
515: * @return should limit
516: */
517: public boolean isLimitRssEntry() {
518: return isLimitRssEntry;
519: }
520:
521: /**
522: * Indicates if the body of RSS entries should be truncated by default
523: *
524: * @param b should limit
525: */
526: public void setLimitRssEntry(boolean b) {
527: isLimitRssEntry = b;
528: }
529:
530: /**
531: * Gets the charset of generated pages
532: *
533: * @return The charset
534: */
535: public String getCharset() {
536: return charset;
537: }
538:
539: /**
540: * Sets the charset of generated pages
541: *
542: * @param string The charset
543: */
544: public void setCharset(String string) {
545: if (java.nio.charset.Charset.isSupported(string))
546: charset = string;
547: }
548: }
|