/* * Created on Jan 31, 2005 * */ package net.sf.thingamablog.generator; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Writer; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Vector; import net.sf.thingamablog.blog.ArchiveRange; import net.sf.thingamablog.blog.TBWeblog; /** * @author Bob Tantlinger * */ public class PageGenerator { /** Constant for the RSS feed */ public static final int RSS_PAGE = -1; /** Constant for the front page */ public static final int FRONT_PAGE = -2; /** Constant for the archive index page */ public static final int INDEX_PAGE = -3; private Vector customTags = new Vector(); private String charset = "UTF-8";//default charset //default container attributes private String archiveRangeFormat = "MMMM, dd yyyy"; private boolean spanArcRange = true; private String dateFormat = archiveRangeFormat; private String timeFormat = "h:mm a"; private int frontPageLimit = 10; private boolean isLimitFrontPage = true; private int categoryPageLimit = 20; private boolean isLimitCategoryPage = true; private boolean isFrontPageAscending; private boolean isCategoryPageAscending; private boolean isArchivePageAscending; private boolean isLimitRssEntry = true; private TemplateProcessor pageBuilder = new TemplateProcessor(); public PageGenerator() { } private void writePage(BlogPageContainer bpc, String template, OutputStream out) throws IOException { writePage(bpc, null, template, out); } private void writePage(BlogPageContainer bpc, BlogEntryContainer bec, String template, OutputStream out) throws IOException { for(int i = 0; i < customTags.size(); i++) bpc.addCustomTag((CustomTag)customTags.elementAt(i)); Writer writer = new OutputStreamWriter(out, charset); PrintWriter pw = new PrintWriter(writer); String rootName = BlogPageContainer.NAME; template = "<" + rootName + ">" + template + "</" + rootName + ">"; String text = pageBuilder.processTemplate(template, bpc); /* * Writing all the entries for a page to a string * would be memeory-intensive if there are a lot of entries. * Thus, it seems safer and more effecient to write the * entries directly to disk. */ if(bec != null) { List entryTmpls = pageBuilder.parseContainers(text, bec); if(entryTmpls.size() == 0)//no entry containers found { pw.write(text); } else { Iterator it = entryTmpls.iterator(); int pos = 0; while(it.hasNext()) { String ec = it.next().toString(); int ecPos = text.indexOf(ec, pos); String part = text.substring(pos, ecPos); writer.write(part); pageBuilder.writeContainer(ec, bec, writer); pos = ecPos + ec.length(); } writer.write(text.substring(pos, text.length())); } } else { pw.write(text); } writer.close(); pw.close(); } /** * Generate a category page * * @param blog The weblog from which the page will be generated * @param cat The category * @param out The OutputStream to write the page to * @param template The template */ public void generatePage(TBWeblog blog, String cat, OutputStream out, String template) throws IOException { BlogPageContainer bpc = new BlogPageContainer(blog, cat, charset); BlogEntryContainer bec = new BlogEntryContainer(blog, cat); bec.setDefaultSortOrder(isCategoryPageAscending); bec.setDefaultDateFormat(dateFormat); bec.setDefaultTimeFormat(timeFormat); bec.setDefaultIsLimit(isLimitCategoryPage); bec.setDefaultLimitBy(categoryPageLimit); bpc.addContainer(new CalendarContainer(blog, cat)); bpc.addContainer(new CategoryListContainer(blog)); bpc.addContainer(new ArchiveYearsContainer(blog, archiveRangeFormat, spanArcRange)); bpc.addContainer(new ArchiveListContainer(blog, archiveRangeFormat, spanArcRange)); bpc.addContainer(new NextPreviousContainer(blog, cat, NextPreviousContainer.NEXT)); bpc.addContainer(new NextPreviousContainer(blog, cat, NextPreviousContainer.PREV)); bpc.addContainer(new IncludeContainer()); //bpc.addContainer(bec); //writePage(bpc, template, out); writePage(bpc, bec, template, out); } /** * Generate an archive page * * @param blog The weblog * @param arc The archive of the page * @param out The OutputStream to write the page to * @param template The template */ public void generatePage(TBWeblog blog, ArchiveRange arc, OutputStream out, String template) throws IOException { BlogPageContainer bpc = new BlogPageContainer(blog, formatArcRange(arc, blog.getLocale()), charset); BlogEntryContainer bec = new BlogEntryContainer(blog, arc); bec.setDefaultSortOrder(isArchivePageAscending); bec.setDefaultDateFormat(dateFormat); bec.setDefaultTimeFormat(timeFormat); bpc.addContainer(new CalendarContainer(blog, arc)); bpc.addContainer(new CategoryListContainer(blog)); bpc.addContainer(new ArchiveYearsContainer(blog, archiveRangeFormat, spanArcRange)); bpc.addContainer(new ArchiveListContainer(blog, archiveRangeFormat, spanArcRange)); bpc.addContainer(new NextPreviousContainer(blog, arc, NextPreviousContainer.NEXT)); bpc.addContainer(new NextPreviousContainer(blog, arc, NextPreviousContainer.PREV)); bpc.addContainer(new IncludeContainer()); //bpc.addContainer(bec); //writePage(bpc, template, out); writePage(bpc, bec, template, out); } private String formatArcRange(ArchiveRange ar, Locale locale) { java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(archiveRangeFormat, locale); String s = sdf.format(ar.getStartDate()); if(spanArcRange) s += " - " + sdf.format(ar.getExpirationDate()); return s; } public void generatePage(TBWeblog blog, long id, OutputStream out, String template) throws IOException { String title; try { title = blog.getEntry(id).getTitle(); } catch(Exception ex) { title = blog.getTitle(); } BlogPageContainer bpc = new BlogPageContainer(blog, title, charset); BlogEntryContainer container = new BlogEntryContainer(blog, id); container.setDefaultDateFormat(dateFormat); container.setDefaultTimeFormat(timeFormat); //container.setDefaultIsLimit(isLimitFrontPage); //container.setDefaultLimitBy(frontPageLimit); //container.setDefaultSortOrder(isFrontPageAscending); //bpc.addContainer(container); bpc.addContainer(new CategoryListContainer(blog)); bpc.addContainer(new ArchiveYearsContainer(blog, archiveRangeFormat, spanArcRange)); bpc.addContainer(new ArchiveListContainer(blog, archiveRangeFormat, spanArcRange)); bpc.addContainer(new NextPreviousContainer(blog, id, NextPreviousContainer.NEXT)); bpc.addContainer(new NextPreviousContainer(blog, id, NextPreviousContainer.PREV)); bpc.addContainer(new IncludeContainer()); writePage(bpc, container, template, out); //writePage(bpc, template, out); } /** * Generate a front page, rss feed, or archive index page * * @param blog The weblog * @param type The type of the page: FONT_PAGE, INDEX_PAGE, RSS_PAGE * @param out The OutputStream to write the page to * @param template The template */ public void generatePage(TBWeblog blog, int type, OutputStream out, String template) throws IOException { BlogPageContainer bpc = new BlogPageContainer(blog, blog.getTitle(), charset); if(type == RSS_PAGE) { BlogEntryContainer container = new BlogEntryContainer(blog, BlogEntryContainer.RSS_PAGE); container.setLimitEntryBody(isLimitRssEntry); container.setDefaultIsLimit(isLimitFrontPage); container.setDefaultLimitBy(frontPageLimit); container.setDefaultSortOrder(false); writePage(bpc, container, template, out); return; } bpc.addContainer(new CalendarContainer(blog)); bpc.addContainer(new CategoryListContainer(blog)); bpc.addContainer(new ArchiveYearsContainer(blog, archiveRangeFormat, spanArcRange)); bpc.addContainer(new ArchiveListContainer(blog, archiveRangeFormat, spanArcRange)); bpc.addContainer(new NextPreviousContainer(NextPreviousContainer.NEXT)); bpc.addContainer(new NextPreviousContainer(NextPreviousContainer.PREV)); bpc.addContainer(new IncludeContainer()); if(type == FRONT_PAGE) { BlogEntryContainer container = new BlogEntryContainer(blog, BlogEntryContainer.FRONT_PAGE); container.setDefaultDateFormat(dateFormat); container.setDefaultTimeFormat(timeFormat); container.setDefaultIsLimit(isLimitFrontPage); container.setDefaultLimitBy(frontPageLimit); container.setDefaultSortOrder(isFrontPageAscending); writePage(bpc, container, template, out); return; } writePage(bpc, template, out); } /** * Adds a custom tag to the generator * * @param tag The CustomTag */ public void addCustomTag(CustomTag tag) { if(!customTags.contains(tag)) customTags.add(tag); } /** * Removes a custom tag from the generator * * @param tag The CustomTag */ public void removeCustomTag(CustomTag tag) { customTags.remove(tag); } /** * Sets all the custom tags for the generator * * @param tags The CustomTags */ public void setCustomTags(CustomTag tags[]) { customTags.removeAllElements(); for(int i = 0; i < tags.length; i++) { customTags.add(tags[i]); } } /** * Gets all the custom tags from the generator * * @return an array of CustomTags */ public CustomTag[] getCustomTags() { CustomTag tags[] = new CustomTag[customTags.size()]; for(int i = 0; i < tags.length; i++) { tags[i] = (CustomTag)customTags.elementAt(i); } return tags; } /** * Gets the default ArchiveRange format * * @return The format */ public String getArchiveRangeFormat() { return archiveRangeFormat; } /** * Gets the default category page limit * * @return The limit */ public int getCategoryPageLimit() { return categoryPageLimit; } /** * Gets the default date format * * @return The format */ public String getDateFormat() { return dateFormat; } /** * Gets the default front page limit * * @return The limit */ public int getFrontPageLimit() { return frontPageLimit; } /** * Indicates if entries are written in * ascending order by default for archive pages * * @return true if ascending, false otherwise */ public boolean isArchivePageAscending() { return isArchivePageAscending; } /** * Indicates if category page entries are written * in ascending order by default * * @return true if ascending, false otherwise */ public boolean isCategoryPageAscending() { return isCategoryPageAscending; } /** * Indicates if front page entries are written * in ascending order by default * * @return true if ascending, false otherwise */ public boolean isFrontPageAscending() { return isFrontPageAscending; } /** * Indicates if entries on category pages should be limited by default * * @return true if limit, false otherwise */ public boolean isLimitCategoryPage() { return isLimitCategoryPage; } /** * Indicates if entries on the front page should be limited by default * * @return true if limit, false otherwise */ public boolean isLimitFrontPage() { return isLimitFrontPage; } /** * Indicates if archive list formated dates should include both dates * * @return true if span, false otherwise */ public boolean isSpanArcRange() { return spanArcRange; } /** * Gets the default time format * * @return The format */ public String getTimeFormat() { return timeFormat; } /** * Sets the default ArchiveRange format * * @param string The format * @param span should span */ public void setArchiveRangeFormat(String string, boolean span) { archiveRangeFormat = string; spanArcRange = span; } /** * Sets the default entry limit for category pages * * @param i The limit */ public void setCategoryPageLimit(int i) { categoryPageLimit = i; } /** * Sets the default date format * * @param string The format */ public void setDateFormat(String string) { dateFormat = string; } /** * Sets the default front page entry limit * * @param i The limit */ public void setFrontPageLimit(int i) { frontPageLimit = i; } /** * Sets the default chronological sort order of entries on archive pages * * @param b The sort order */ public void setArchivePageAscending(boolean b) { isArchivePageAscending = b; } /** * Sets the default chronological sort order of entries on category pages * * @param The sort order */ public void setCategoryPageAscending(boolean b) { isCategoryPageAscending = b; } /** * Sets the default chronological sort order of entries on the front page * * @param b The sort order */ public void setFrontPageAscending(boolean b) { isFrontPageAscending = b; } /** * Sets the default limit policy for category pages * * @param b should limit */ public void setLimitCategoryPage(boolean b) { isLimitCategoryPage = b; } /** * Sets the default limit policy for the front page * * @param b should limit */ public void setLimitFrontPage(boolean b) { isLimitFrontPage = b; } /** * Sets the default time format * * @param string The format */ public void setTimeFormat(String string) { timeFormat = string; } /** * Indicates if the body of RSS entries should be truncated by default * * @return should limit */ public boolean isLimitRssEntry() { return isLimitRssEntry; } /** * Indicates if the body of RSS entries should be truncated by default * * @param b should limit */ public void setLimitRssEntry(boolean b) { isLimitRssEntry = b; } /** * Gets the charset of generated pages * * @return The charset */ public String getCharset() { return charset; } /** * Sets the charset of generated pages * * @param string The charset */ public void setCharset(String string) { if(java.nio.charset.Charset.isSupported(string)) charset = string; } }