//# 3 errors, 143 messages
//#
/*
    //#calendartag.java:1:1: class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#calendartag.java:1:1: method: net.sourceforge.pebble.web.tagext.CalendarTag.net.sourceforge.pebble.web.tagext.CalendarTag__static_init
 * Copyright (c) 2003-2006, Simon Brown
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   - Neither the name of Pebble nor the names of its contributors may
 *     be used to endorse or promote products derived from this software
 *     without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package net.sourceforge.pebble.web.tagext;

import java.io.IOException;
import java.text.DateFormatSymbols;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

import net.sourceforge.pebble.Constants;
import net.sourceforge.pebble.domain.Blog;
import net.sourceforge.pebble.domain.Day;
import net.sourceforge.pebble.domain.Month;
import net.sourceforge.pebble.util.I18n;
import net.sourceforge.pebble.util.UrlRewriter;

/**
 * A custom tag that outputs a calendar control.
 *
 * @author    Simon Brown
 */
public class CalendarTag extends TagSupport {
    //#calendartag.java:61: method: void net.sourceforge.pebble.web.tagext.CalendarTag.net.sourceforge.pebble.web.tagext.CalendarTag()
    //#input(void net.sourceforge.pebble.web.tagext.CalendarTag()): this
    //#calendartag.java:61: end of method: void net.sourceforge.pebble.web.tagext.CalendarTag.net.sourceforge.pebble.web.tagext.CalendarTag()

  /**
   * Implementation from the Tag interface - this is called when the opening tag
   * is encountered.
   *
   * @return  an integer specifying what to do afterwards
   * @throws  JspException    if something goes wrong
   */
  public int doStartTag() throws JspException {

    HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
    //#calendartag.java:72: method: int net.sourceforge.pebble.web.tagext.CalendarTag.doStartTag()
    //#input(int doStartTag()): net.sourceforge.pebble.PebbleContext__static_init.new PebbleContext(PebbleContext__static_init#1).__Tag
    //#input(int doStartTag()): net/sourceforge/pebble/PebbleContext.__Descendant_Table[net/sourceforge/pebble/PebbleContext]
    //#input(int doStartTag()): net/sourceforge/pebble/PebbleContext.__Dispatch_Table.getConfiguration()Lnet/sourceforge/pebble/Configuration;
    //#input(int doStartTag()): net/sourceforge/pebble/PebbleContext.instance
    //#input(int doStartTag()): net/sourceforge/pebble/util/HttpsURLRewriter.__Dispatch_Table.rewrite(Ljava/lang/String;)Ljava/lang/String;
    //#input(int doStartTag()): net/sourceforge/pebble/util/NullUrlRewriter.__Dispatch_Table.rewrite(Ljava/lang/String;)Ljava/lang/String;
    //#input(int doStartTag()): net/sourceforge/pebble/util/UrlRewriter.__Descendant_Table[net/sourceforge/pebble/util/HttpsURLRewriter]
    //#input(int doStartTag()): net/sourceforge/pebble/util/UrlRewriter.__Descendant_Table[net/sourceforge/pebble/util/NullUrlRewriter]
    //#input(int doStartTag()): net/sourceforge/pebble/util/UrlRewriter.__Descendant_Table[net/sourceforge/pebble/util/UrlRewriter]
    //#input(int doStartTag()): net/sourceforge/pebble/util/UrlRewriter.__Descendant_Table[others]
    //#input(int doStartTag()): net/sourceforge/pebble/util/UrlRewriter.__Dispatch_Table.rewrite(Ljava/lang/String;)Ljava/lang/String;
    //#input(int doStartTag()): net/sourceforge/pebble/util/UrlRewriter.x
    //#input(int doStartTag()): this
    //#input(int doStartTag()): this.pageContext
    //#output(int doStartTag()): return_value
    //#pre[2] (int doStartTag()): net/sourceforge/pebble/util/UrlRewriter.x != null
    //#pre[4] (int doStartTag()): this.pageContext != null
    //#presumption(int doStartTag()): days.length@118 >= 2
    //#presumption(int doStartTag()): java.util.Calendar:getFirstDayOfWeek(...)@114 < days.length@118
    //#presumption(int doStartTag()): java.text.DateFormatSymbols:getShortWeekdays(...)@118 != null
    //#presumption(int doStartTag()): java.text.NumberFormat:format(...)@136 != null
    //#presumption(int doStartTag()): java.text.NumberFormat:getIntegerInstance(...)@89 != null
    //#presumption(int doStartTag()): java.util.Calendar:getFirstDayOfWeek(...)@114 >= 0
    //#presumption(int doStartTag()): java.util.Iterator:next(...)@133 != null
    //#presumption(int doStartTag()): javax.servlet.http.HttpServletRequest:getAttribute(...)@73 != null
    //#presumption(int doStartTag()): javax.servlet.jsp.PageContext:getOut(...)@94 != null
    //#presumption(int doStartTag()): javax.servlet.jsp.PageContext:getRequest(...)@72 != null
    //#presumption(int doStartTag()): net.sourceforge.pebble.domain.Blog:getBlogForDay(...)@134 != null
    //#presumption(int doStartTag()): net.sourceforge.pebble.domain.Blog:getBlogForToday(...)@75 != null
    //#presumption(int doStartTag()): net.sourceforge.pebble.domain.Blog:getCalendar(...)@76 != null
    //#presumption(int doStartTag()): net.sourceforge.pebble.domain.Blog:getCalendar(...)@82 != null
    //#presumption(int doStartTag()): net.sourceforge.pebble.domain.Month:getBlogForDay(...)@83 != null
    //#presumption(int doStartTag()): net.sourceforge.pebble.domain.Month:getDate(...)@195 != null
    //#presumption(int doStartTag()): net.sourceforge.pebble.domain.Month:getNextMonth(...)@177 != null
    //#presumption(int doStartTag()): net.sourceforge.pebble.domain.Month:getPreviousMonth(...)@176 != null
    //#post(int doStartTag()): return_value == 0
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(int doStartTag()): Effects-of-calling:net.sourceforge.pebble.domain.Blog:getCalendar
    //#unanalyzed(int doStartTag()): Effects-of-calling:net.sourceforge.pebble.domain.Month:getBlogForDay
    //#unanalyzed(int doStartTag()): Effects-of-calling:net.sourceforge.pebble.domain.Day:getDate
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.Calendar:setTime
    //#unanalyzed(int doStartTag()): Effects-of-calling:net.sourceforge.pebble.domain.Month:getLastDayInMonth
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.Calendar:clone
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.Calendar:set
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.List:add
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.Calendar:get
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.Calendar:getFirstDayOfWeek
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.Calendar:add
    //#unanalyzed(int doStartTag()): Effects-of-calling:net.sourceforge.pebble.util.UrlRewriter$TheRewriter:get
    //#unanalyzed(int doStartTag()): Effects-of-calling:rewrite
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(int doStartTag()): Effects-of-calling:net.sourceforge.pebble.Configuration:getSecureUrl
    //#unanalyzed(int doStartTag()): Effects-of-calling:net.sourceforge.pebble.Configuration:getUrl
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.lang.String:replace
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.ResourceBundle:getBundle
    //#unanalyzed(int doStartTag()): Effects-of-calling:java.util.ResourceBundle:getString
    //#unanalyzed(int doStartTag()): Effects-of-calling:net.sourceforge.pebble.domain.Blog:getLocale
    //#test_vector(int doStartTag()): java.lang.String:length(...)@137: {0, 2..4_294_967_295}, {1}
    //#test_vector(int doStartTag()): java.util.Date:after(...)@195: {1}, {0}
    //#test_vector(int doStartTag()): java.util.Iterator:hasNext(...)@132: {1}, {0}
    //#test_vector(int doStartTag()): javax.servlet.http.HttpServletRequest:getAttribute(...)@74: Inverse{null}, Addr_Set{null}
    //#test_vector(int doStartTag()): net.sourceforge.pebble.domain.Day:hasBlogEntries(...)@152: {0}, {1}
    //#test_vector(int doStartTag()): net.sourceforge.pebble.domain.Day:hasBlogEntries(...)@158: {0}, {1}
    //#test_vector(int doStartTag()): net.sourceforge.pebble.domain.Month:before(...)@100: {0}, {1}
    //#test_vector(int doStartTag()): net.sourceforge.pebble.domain.Month:before(...)@183: {0}, {1}
    //#test_vector(int doStartTag()): net.sourceforge.pebble.domain.Month:before(...)@195: {0}, {1}
    Blog blog = (Blog)request.getAttribute(Constants.BLOG_KEY);
    Month month = (Month)request.getAttribute(Constants.MONTHLY_BLOG);
    Day today = blog.getBlogForToday();
    //#calendartag.java:75: Warning: method not available
    //#    -- call on Day net.sourceforge.pebble.domain.Blog:getBlogForToday()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Day net.sourceforge.pebble.domain.Blog:getBlogForToday()
    Calendar now = blog.getCalendar();
    //#calendartag.java:76: Warning: method not available
    //#    -- call on Calendar net.sourceforge.pebble.domain.Blog:getCalendar()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Calendar net.sourceforge.pebble.domain.Blog:getCalendar()

    if (month == null) {
      month = today.getMonth();
    //#calendartag.java:79: Warning: method not available
    //#    -- call on Month net.sourceforge.pebble.domain.Day:getMonth()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Month net.sourceforge.pebble.domain.Day:getMonth()
    }

    Calendar firstDayOfMonth = blog.getCalendar();
    //#calendartag.java:82: Warning: method not available
    //#    -- call on Calendar net.sourceforge.pebble.domain.Blog:getCalendar()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Calendar net.sourceforge.pebble.domain.Blog:getCalendar()
    firstDayOfMonth.setTime(month.getBlogForDay(1).getDate());
    //#calendartag.java:83: ?null dereference
    //#    month != null
    //#    severity: SUPPRESSED
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    basic block: bb_3
    //#    assertion: month != null
    //#    VN: month
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
    //#calendartag.java:83: Warning: method not available
    //#    -- call on Day net.sourceforge.pebble.domain.Month:getBlogForDay(int)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Day net.sourceforge.pebble.domain.Month:getBlogForDay(int)
    //#calendartag.java:83: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Day:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Day:getDate()

    SimpleDateFormat monthAndYearFormatter = new SimpleDateFormat("MMMM yyyy", blog.getLocale());
    //#calendartag.java:85: Warning: method not available
    //#    -- call on Locale net.sourceforge.pebble.domain.Blog:getLocale()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Locale net.sourceforge.pebble.domain.Blog:getLocale()
    monthAndYearFormatter.setTimeZone(blog.getTimeZone());
    //#calendartag.java:86: Warning: method not available
    //#    -- call on TimeZone net.sourceforge.pebble.domain.Blog:getTimeZone()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: TimeZone net.sourceforge.pebble.domain.Blog:getTimeZone()
    SimpleDateFormat monthFormatter = new SimpleDateFormat("MMM", blog.getLocale());
    //#calendartag.java:87: Warning: method not available
    //#    -- call on Locale net.sourceforge.pebble.domain.Blog:getLocale()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Locale net.sourceforge.pebble.domain.Blog:getLocale()
    monthFormatter.setTimeZone(blog.getTimeZone());
    //#calendartag.java:88: Warning: method not available
    //#    -- call on TimeZone net.sourceforge.pebble.domain.Blog:getTimeZone()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: TimeZone net.sourceforge.pebble.domain.Blog:getTimeZone()
    NumberFormat numberFormatter = NumberFormat.getIntegerInstance(blog.getLocale());
    //#calendartag.java:89: Warning: method not available
    //#    -- call on Locale net.sourceforge.pebble.domain.Blog:getLocale()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Locale net.sourceforge.pebble.domain.Blog:getLocale()

    Month firstMonth = blog.getBlogForFirstMonth();
    //#calendartag.java:91: Warning: method not available
    //#    -- call on Month net.sourceforge.pebble.domain.Blog:getBlogForFirstMonth()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Month net.sourceforge.pebble.domain.Blog:getBlogForFirstMonth()

    try {
      JspWriter out = pageContext.getOut();

      out.write("<div class=\"calendar\">");
      out.write("<table width=\"100%\">");
      out.write("<tr>");
      out.write("<td colspan=\"7\" align=\"center\">");
      if (month.before(firstMonth)) {
    //#calendartag.java:100: Warning: method not available
    //#    -- call on bool net.sourceforge.pebble.domain.Month:before(Month)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: bool net.sourceforge.pebble.domain.Month:before(Month)
        out.write("<b>");
        out.write(monthAndYearFormatter.format(month.getDate()));
    //#calendartag.java:102: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Month:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Month:getDate()
        out.write("</b>");
      } else {
        out.write("<b><a href=\"");
        out.write(UrlRewriter.doRewrite(month.getPermalink()));
    //#calendartag.java:106: Warning: method not available
    //#    -- call on String net.sourceforge.pebble.domain.Month:getPermalink()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: String net.sourceforge.pebble.domain.Month:getPermalink()
        out.write("\">");
        out.write(monthAndYearFormatter.format(month.getDate()));
    //#calendartag.java:108: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Month:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Month:getDate()
        out.write("</a></b>");
      }
      out.write("</td>");
      out.write("</tr>");

      int firstDayOfWeek = now.getFirstDayOfWeek();

      // write out the calendar header
      DateFormatSymbols symbols = new DateFormatSymbols(blog.getLocale());
    //#calendartag.java:117: Warning: method not available
    //#    -- call on Locale net.sourceforge.pebble.domain.Blog:getLocale()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Locale net.sourceforge.pebble.domain.Blog:getLocale()
      String[] days = symbols.getShortWeekdays();
      out.write("<tr>");
      for (int i = firstDayOfWeek; i <= 7; i++) {
        out.write("<td class=\"calendarDayHeader\" width=\"14%\">" + days[i] + "</td>");
    //#calendartag.java:121: ?array index out of bounds
    //#    i < days.length
    //#    severity: MEDIUM
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    basic block: bb_8
    //#    assertion: i < days.length
    //#    VN: -(i - days.length@118)
    //#    Expected: {1..+Inf}
    //#    Bad: {0}
    //#    Attribs:  Int  Bad singleton  Bad overlaps +/-1000  Bad < Exp
      }
      for (int i = 1; i < firstDayOfWeek; i++) {
        out.write("<td class=\"calendarDayHeader\">" + days[i] + "</td>");
      }
      out.write("</tr>");

      // write out the body of the calendar
      Iterator it = getDatesForCompleteWeeks(blog, month).iterator();
      Calendar cal;
      int count = 0;
      while (it.hasNext()) {
        cal = (Calendar)it.next();
        Day daily = blog.getBlogForDay(cal.getTime());
    //#calendartag.java:134: Warning: method not available
    //#    -- call on Day net.sourceforge.pebble.domain.Blog:getBlogForDay(Date)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Day net.sourceforge.pebble.domain.Blog:getBlogForDay(Date)

        String formattedNumber = numberFormatter.format(cal.get(Calendar.DAY_OF_MONTH));
        if (formattedNumber.length() == 1) {
          formattedNumber = "&nbsp;" + formattedNumber;
        }

        if (count % 7 == 0) {
          out.write("<tr>");
        }

        // output padding if the date to display isn't in the month
        if (cal.get(Calendar.MONTH) != firstDayOfMonth.get(Calendar.MONTH)) {
          out.write("<td class=\"calendarDay\">&nbsp;");
        } else if (now.get(Calendar.YEAR) == cal.get(Calendar.YEAR) &&
          now.get(Calendar.MONTH) == cal.get(Calendar.MONTH) &&
          now.get(Calendar.DAY_OF_MONTH) == cal.get(Calendar.DAY_OF_MONTH)) {
          out.write("<td class=\"calendarToday\">");
          if (daily.hasBlogEntries()) {
    //#calendartag.java:152: Warning: method not available
    //#    -- call on bool net.sourceforge.pebble.domain.Day:hasBlogEntries()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: bool net.sourceforge.pebble.domain.Day:hasBlogEntries()
            out.write("&nbsp;<a href=\"" + UrlRewriter.doRewrite(daily.getPermalink()) + "\">" + formattedNumber + "</a>&nbsp;");
    //#calendartag.java:153: Warning: method not available
    //#    -- call on String net.sourceforge.pebble.domain.Day:getPermalink()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: String net.sourceforge.pebble.domain.Day:getPermalink()
          } else {
            out.write("&nbsp;" + formattedNumber + "&nbsp;");
          }
        } else {
          if (daily.hasBlogEntries()) {
    //#calendartag.java:158: Warning: method not available
    //#    -- call on bool net.sourceforge.pebble.domain.Day:hasBlogEntries()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: bool net.sourceforge.pebble.domain.Day:hasBlogEntries()
            out.write("<td class=\"calendarDayWithEntries\">");
            out.write("&nbsp;<a href=\"" + UrlRewriter.doRewrite(daily.getPermalink()) + "\">" + formattedNumber + "</a>&nbsp;");
    //#calendartag.java:160: Warning: method not available
    //#    -- call on String net.sourceforge.pebble.domain.Day:getPermalink()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: String net.sourceforge.pebble.domain.Day:getPermalink()
          } else {
            out.write("<td class=\"calendarDay\">");
            out.write("&nbsp;" + formattedNumber + "&nbsp;");
          }
        }
        out.write("</td>");

        if (count % 7 == 6) {
          out.write("</tr>");
        }

        count++;
    //#calendartag.java:172: ?overflow
    //#    count in -2_147_483_649..4_294_967_294
    //#    severity: LOW
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    basic block: bb_31
    //#    assertion: count in -2_147_483_649..4_294_967_294
    //#    VN: count + 1
    //#    Expected: {-2_147_483_648..4_294_967_295, Invalid}
    //#    Bad: {4_294_967_296}
    //#    Attribs:  Int  Bad singleton  Bad > Exp
      }

      // write out the footer of the calendar
      Month previous = month.getPreviousMonth();
    //#calendartag.java:176: Warning: method not available
    //#    -- call on Month net.sourceforge.pebble.domain.Month:getPreviousMonth()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Month net.sourceforge.pebble.domain.Month:getPreviousMonth()
      Month next = month.getNextMonth();
    //#calendartag.java:177: Warning: method not available
    //#    -- call on Month net.sourceforge.pebble.domain.Month:getNextMonth()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Month net.sourceforge.pebble.domain.Month:getNextMonth()

      out.write("<tr>");
      out.write("<td colspan=\"7\" align=\"center\">");

      // only display the previous month link if there are blog entries
      if (previous.before(firstMonth)) {
    //#calendartag.java:183: Warning: method not available
    //#    -- call on bool net.sourceforge.pebble.domain.Month:before(Month)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: bool net.sourceforge.pebble.domain.Month:before(Month)
        out.write(monthFormatter.format(previous.getDate()));
    //#calendartag.java:184: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Month:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Month:getDate()
      } else {
        out.write("<a href=\"" + UrlRewriter.doRewrite(previous.getPermalink()) + "\">" + monthFormatter.format(previous.getDate()) + "</a>");
    //#calendartag.java:186: Warning: method not available
    //#    -- call on String net.sourceforge.pebble.domain.Month:getPermalink()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: String net.sourceforge.pebble.domain.Month:getPermalink()
    //#calendartag.java:186: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Month:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Month:getDate()
      }

      String todayText = I18n.getMessage(blog, "common.today");
      out.write("&nbsp; | &nbsp;");
      out.write("<a href=\"" + UrlRewriter.doRewrite(today.getPermalink()) + "\">" + todayText + "</a>");
    //#calendartag.java:191: Warning: method not available
    //#    -- call on String net.sourceforge.pebble.domain.Day:getPermalink()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: String net.sourceforge.pebble.domain.Day:getPermalink()
      out.write("&nbsp; | &nbsp;");

      // only display the next month date if it's not in the future
      if (next.getDate().after(now.getTime()) || next.before(firstMonth)) {
    //#calendartag.java:195: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Month:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Month:getDate()
    //#calendartag.java:195: Warning: method not available
    //#    -- call on bool net.sourceforge.pebble.domain.Month:before(Month)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: bool net.sourceforge.pebble.domain.Month:before(Month)
        out.write(monthFormatter.format(next.getDate()));
    //#calendartag.java:196: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Month:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Month:getDate()
      } else {
        out.write("<a href=\"" + UrlRewriter.doRewrite(next.getPermalink()) + "\">" + monthFormatter.format(next.getDate()) + "</a>");
    //#calendartag.java:198: Warning: method not available
    //#    -- call on String net.sourceforge.pebble.domain.Month:getPermalink()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: String net.sourceforge.pebble.domain.Month:getPermalink()
    //#calendartag.java:198: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Month:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: int doStartTag()
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Month:getDate()
      }
      out.write("</td>");
      out.write("</tr>");

      out.write("</table>");
      out.write("</div>");
    } catch (IOException ioe) {
      throw new JspTagException(ioe.getMessage());
    }

    return SKIP_BODY;
    //#calendartag.java:209: end of method: int net.sourceforge.pebble.web.tagext.CalendarTag.doStartTag()
  }

  /**
   * Gets a list of dates that should be displayed for the given month. This
   * method adds dates either side of the month, padding the list so that it
   * contains a number of complete weeks. For example, if the first day of the
   * month for the blog's locale is Monday and the given month starts on a
   * Tuesday, this method will add in that previous Monday to present
   * back a complete week. The same happens for the end of the month. This
   * makes rendering easier since we just have a 7xN grid.
   *
   * @param blog    a Blog instance
   * @param month   the month
   * @return  a List of Calendar instances
   */
  private List getDatesForCompleteWeeks(Blog blog, Month month) {
    List dates = new ArrayList();
    //#calendartag.java:226: method: List net.sourceforge.pebble.web.tagext.CalendarTag.getDatesForCompleteWeeks(Blog, Month)
    //#input(List getDatesForCompleteWeeks(Blog, Month)): blog
    //#input(List getDatesForCompleteWeeks(Blog, Month)): month
    //#output(List getDatesForCompleteWeeks(Blog, Month)): new ArrayList(getDatesForCompleteWeeks#1) num objects
    //#output(List getDatesForCompleteWeeks(Blog, Month)): return_value
    //#new obj(List getDatesForCompleteWeeks(Blog, Month)): new ArrayList(getDatesForCompleteWeeks#1)
    //#pre[1] (List getDatesForCompleteWeeks(Blog, Month)): blog != null
    //#pre[2] (List getDatesForCompleteWeeks(Blog, Month)): month != null
    //#presumption(List getDatesForCompleteWeeks(Blog, Month)): net.sourceforge.pebble.domain.Blog:getCalendar(...)@227 != null
    //#presumption(List getDatesForCompleteWeeks(Blog, Month)): net.sourceforge.pebble.domain.Blog:getCalendar(...)@229 != null
    //#presumption(List getDatesForCompleteWeeks(Blog, Month)): net.sourceforge.pebble.domain.Month:getBlogForDay(...)@228 != null
    //#presumption(List getDatesForCompleteWeeks(Blog, Month)): net.sourceforge.pebble.domain.Month:getBlogForDay(...)@230 != null
    //#presumption(List getDatesForCompleteWeeks(Blog, Month)): net.sourceforge.pebble.domain.Month:getLastDayInMonth(...)@234 <= 4_294_967_294
    //#post(List getDatesForCompleteWeeks(Blog, Month)): return_value == &new ArrayList(getDatesForCompleteWeeks#1)
    //#post(List getDatesForCompleteWeeks(Blog, Month)): new ArrayList(getDatesForCompleteWeeks#1) num objects == 1
    Calendar start = blog.getCalendar();
    //#calendartag.java:227: Warning: method not available
    //#    -- call on Calendar net.sourceforge.pebble.domain.Blog:getCalendar()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: List getDatesForCompleteWeeks(Blog, Month)
    //#    unanalyzed callee: Calendar net.sourceforge.pebble.domain.Blog:getCalendar()
    start.setTime(month.getBlogForDay(1).getDate());
    //#calendartag.java:228: Warning: method not available
    //#    -- call on Day net.sourceforge.pebble.domain.Month:getBlogForDay(int)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: List getDatesForCompleteWeeks(Blog, Month)
    //#    unanalyzed callee: Day net.sourceforge.pebble.domain.Month:getBlogForDay(int)
    //#calendartag.java:228: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Day:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: List getDatesForCompleteWeeks(Blog, Month)
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Day:getDate()
    Calendar end = blog.getCalendar();
    //#calendartag.java:229: Warning: method not available
    //#    -- call on Calendar net.sourceforge.pebble.domain.Blog:getCalendar()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: List getDatesForCompleteWeeks(Blog, Month)
    //#    unanalyzed callee: Calendar net.sourceforge.pebble.domain.Blog:getCalendar()
    end.setTime(month.getBlogForDay(month.getLastDayInMonth()).getDate());
    //#calendartag.java:230: Warning: method not available
    //#    -- call on int net.sourceforge.pebble.domain.Month:getLastDayInMonth()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: List getDatesForCompleteWeeks(Blog, Month)
    //#    unanalyzed callee: int net.sourceforge.pebble.domain.Month:getLastDayInMonth()
    //#calendartag.java:230: Warning: method not available
    //#    -- call on Day net.sourceforge.pebble.domain.Month:getBlogForDay(int)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: List getDatesForCompleteWeeks(Blog, Month)
    //#    unanalyzed callee: Day net.sourceforge.pebble.domain.Month:getBlogForDay(int)
    //#calendartag.java:230: Warning: method not available
    //#    -- call on Date net.sourceforge.pebble.domain.Day:getDate()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: List getDatesForCompleteWeeks(Blog, Month)
    //#    unanalyzed callee: Date net.sourceforge.pebble.domain.Day:getDate()
    Calendar cal;

    // put all days in month into a list
    for (int i = 1; i <= month.getLastDayInMonth(); i++) {
    //#calendartag.java:234: Warning: method not available
    //#    -- call on int net.sourceforge.pebble.domain.Month:getLastDayInMonth()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.web.tagext.CalendarTag
    //#    method: List getDatesForCompleteWeeks(Blog, Month)
    //#    unanalyzed callee: int net.sourceforge.pebble.domain.Month:getLastDayInMonth()
      cal = (Calendar)start.clone();
      cal.set(Calendar.DAY_OF_MONTH, i);
      dates.add(cal);
    }

    // pad out before the start of the month, until the first day of the week
    cal = (Calendar)start.clone();
    while (cal.get(Calendar.DAY_OF_WEEK) != cal.getFirstDayOfWeek()) {
      cal.add(Calendar.DATE, -1);
      dates.add(0, cal.clone());
    }

    // pad out after month, until the last day of the week
    cal = (Calendar)end.clone();
    cal.add(Calendar.DATE, 1);
    while (cal.get(Calendar.DAY_OF_WEEK) != cal.getFirstDayOfWeek()) {
      dates.add(cal.clone());
      cal.add(Calendar.DATE, 1);
    }

    return dates;
    //#calendartag.java:255: end of method: List net.sourceforge.pebble.web.tagext.CalendarTag.getDatesForCompleteWeeks(Blog, Month)
  }

}    //#output(net.sourceforge.pebble.web.tagext.CalendarTag__static_init): __Descendant_Table[net/sourceforge/pebble/web/tagext/CalendarTag]
    //#output(net.sourceforge.pebble.web.tagext.CalendarTag__static_init): __Dispatch_Table.doStartTag()I
    //#output(net.sourceforge.pebble.web.tagext.CalendarTag__static_init): __Dispatch_Table.getDatesForCompleteWeeks(Lnet/sourceforge/pebble/domain/Blog;Lnet/sourceforge/pebble/domain/Month;)Ljava/util/List;
    //#post(net.sourceforge.pebble.web.tagext.CalendarTag__static_init): __Descendant_Table[net/sourceforge/pebble/web/tagext/CalendarTag] == &__Dispatch_Table
    //#post(net.sourceforge.pebble.web.tagext.CalendarTag__static_init): __Dispatch_Table.doStartTag()I == &doStartTag
    //#post(net.sourceforge.pebble.web.tagext.CalendarTag__static_init): __Dispatch_Table.getDatesForCompleteWeeks(Lnet/sourceforge/pebble/domain/Blog;Lnet/sourceforge/pebble/domain/Month;)Ljava/util/List; == &getDatesForCompleteWeeks
    //#calendartag.java:: end of method: net.sourceforge.pebble.web.tagext.CalendarTag.net.sourceforge.pebble.web.tagext.CalendarTag__static_init
    //#calendartag.java:: end of class: net.sourceforge.pebble.web.tagext.CalendarTag
