/* ======================================================================
The Bodington System Software License, Version 1.0

Copyright (c) 2001 The University of Leeds.  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

1.  Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2.  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.

3.  The end-user documentation included with the redistribution, if any,
must include the following acknowledgement:  "This product includes
software developed by the University of Leeds
(http://www.bodington.org/)."  Alternately, this acknowledgement may
appear in the software itself, if and wherever such third-party
acknowledgements normally appear.

4.  The names "Bodington", "Nathan Bodington", "Bodington System",
"Bodington Open Source Project", and "The University of Leeds" must not be
used to endorse or promote products derived from this software without
prior written permission. For written permission, please contact
d.gardner@leeds.ac.uk.

5.  The name "Bodington" may not appear in the name of products derived
from this software without prior written permission of the University of
Leeds.

THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO,  TITLE,  THE IMPLIED WARRANTIES
OF QUALITY  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
EVENT SHALL THE UNIVERSITY OF LEEDS OR ITS 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.
=========================================================

This software was originally created by the University of Leeds and may contain voluntary
contributions from others.  For more information on the Bodington Open Source Project, please
see http://bodington.org/

====================================================================== */

package org.bodington.servlet.facilities;

import org.bodington.servlet.Request;
import org.bodington.servlet.template.Template;

import org.bodington.server.resources.Resource;
import org.bodington.server.resources.NewsFeedResource;
import org.bodington.server.BuildingServerException;
import org.bodington.server.BuildingContext;
import org.bodington.server.realm.Permission;

import java.io.PrintWriter;
import java.io.IOException;
import java.util.logging.*;

//import org.bodington.database.PrimaryKey;
//import org.bodington.server.BuildingContext;
//import org.bodington.server.BuildingServer;
//import org.bodington.server.BuildingServerException;
import org.bodington.server.realm.User;
import org.w3c.dom.Document;
import org.jafer.util.xml.*;
import org.jafer.exception.JaferException;

import javax.xml.transform.Templates;

import java.net.URL;
import java.net.MalformedURLException;
import java.net.HttpURLConnection;
import java.io.InputStream;
import java.io.StringWriter;
//import java.io.IOException;
//import java.util.logging.*;
import java.util.Hashtable;

import javax.servlet.ServletException;


public class NewsFeedFacility extends Facility {

    private static String TRANSFORM_STYLESHEET = "/org/bodington/xsl/feedTransform.xsl";
    private Templates stylesheetTemplate;
    private String statusMessage;
    
    public NewsFeedFacility() throws BuildingServerException
    {
//        try
//        {
//          TODO: get this working:
//            createStylesheetTemplate(TRANSFORM_STYLESHEET);
//        }
//        catch (JaferException ex)
//        {
//            String message = "Error loading XSL stylesheet for NewsFeed resource";
//            Logger.getLogger("org.bodington.server").severe(message);
//            throw new BuildingServerException(ex.getMessage(), message);
//        }
    }

  public Resource newResource()
  {
    try {
      return new NewsFeedResource();
    }
    catch (BuildingServerException ex) { // TODO ??
      return null;
    }
  }

  public boolean initResource( Request breq, Resource new_resource )
      throws BuildingServerException
  {
    String url;

    if ( !(new_resource instanceof NewsFeedResource) )
      throw new BuildingServerException( "Technical problem: An incorrect type of resource was created." );

    // Only the URL is set at creation time, other properties are set to the defaults.
    if ( breq.getParameter( "newsfeedURL" ) != null )
    {
      url = breq.getParameter( "newsfeedURL" );
      ((NewsFeedResource)new_resource).setFeedURL( url );

      return true;
    }
    return false;
  }

  public void insert( Request req, PrintWriter out, String command, String insertname )
      throws ServletException, IOException
  {
    Logger.getLogger("org.bodington").fine( " NewsFeedFacility insert()" );

    if (!(req.getResource() instanceof NewsFeedResource))
    {
        String message = "Wrong type of resource found, expecting NewsFeed resource";
        Logger.getLogger("org.bodington.server").severe(message);
        return;
    }
    
    NewsFeedResource resource = (NewsFeedResource)req.getResource();

    if ( command.equalsIgnoreCase( "displayfeed" ) )
    {
      String html = getFrameDisplay( resource );
      out.print(html);
      return;
    }

    // TODO Do this another way...
    if (command.equalsIgnoreCase("modifyproperties"))
    {
      if (req.getParameter("savesettings") != null) // Save button has been pushed...
      {
        updateDisplayInline(req, resource);
        updateDisplayImage(req, resource);
        updateDisplayTitle(req, resource);
        updateDisplayDescription(req, resource);
        updateDisplayAuthor(req, resource);
        updateAllowTitleLinks(req, resource);
        updateDisplayDate(req, resource);
        updateMaxNumberOfItems(req, resource);
        updateDisplayItemTitles(req, resource);
        updateDisplayItemAuthors(req, resource);
        updateDisplayItemContent(req, resource);
        updateDisplayExcerpt(req, resource);
        updateDisplayItemDate(req, resource);
        //TODO Don't use in interface yet, not saved to database:
        updateItemSeparationTag(req, resource);
        updateFeedURL(req, resource);
        try
        {
          if (resource.isUnsaved())
            resource.save();
        }
        catch (BuildingServerException ex)
        {
          ex.printStackTrace(out);// TODO
        }
      }
      return;
    }

    if (displayCurrentSettings(command, resource, out))
      return;

    super.insert( req, out, command, insertname );
  }

  private boolean displayCurrentSettings(String command, NewsFeedResource resource, PrintWriter out)
  {
    // returns boolean if command was acted upon.
    if ( command.equalsIgnoreCase("inline"))
     {
       if ( resource.isDisplayInline() )
         out.print("checked");
       return true;
     }
    
    if ( command.equalsIgnoreCase("image"))
    {
      if ( resource.isDisplayImage() )
        out.print("checked");
      return true;
    }

     if ( command.equalsIgnoreCase("title"))
     {
       if ( resource.isDisplayTitle() )
         out.print("checked");
       return true;
     }
     
     if ( command.equalsIgnoreCase("description"))
     {
       if ( resource.isDisplayDescription() )
         out.print("checked");
       return true;
     }

     if ( command.equalsIgnoreCase("author"))
     {
       if ( resource.isDisplayAuthor() )
         out.print("checked");
       return true;
     }
     
     if ( command.equalsIgnoreCase("allowlinks"))
     {
       if ( resource.isAllowTitleLinks() )
         out.print("checked");
       return true;
     }

     if ( command.equalsIgnoreCase("date"))
     {
       if ( resource.isDisplayDate() )
         out.print("checked");
       return true;
     }
     
     if ( command.equalsIgnoreCase("maxnumber"))
     {
       out.print(resource.getMaxNumberOfEntries());
       return true;
     }

     if ( command.equalsIgnoreCase("itemtitles"))
     {
       if ( resource.isDisplayEntryTitles() )
         out.print("checked");
       return true;
     }

     if ( command.equalsIgnoreCase("itemauthors"))
     {
       if ( resource.isDisplayEntryAuthors() )
         out.print("checked");
       return true;
     }

     if ( command.equalsIgnoreCase("content"))
     {
       if ( resource.isDisplayEntryContent() )
         out.print("checked");
       return true;
     }

     if ( command.equalsIgnoreCase("excerpt"))
     {
       if ( resource.isDisplayExcerpt() )
         out.print("checked");
       return true;
     }
     
if ( command.equalsIgnoreCase("itemdate"))
     {
       if ( resource.isDisplayEntryDate() )
         out.print("checked");
       return true;
     }

     if ( command.equalsIgnoreCase("newsfeedURL"))
     {
       out.print(resource.getFeedURL());
       return true;
     }
     
     
     return false;
  }

  private void updateDisplayInline(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("inline") != null && !resource.isDisplayInline())
    {
      resource.setDisplayInline(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("inline") == null && resource.isDisplayInline())
    {
      resource.setDisplayInline(false);
      resource.setUnsaved();
    }
  }

  private void updateMaxNumberOfItems(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("maxnumber") != null)
    {
      String maxNumber = req.getParameter("maxnumber");
      if (!resource.getMaxNumberOfEntries().equals(maxNumber))
        try
        {
          int newMax = Integer.parseInt(maxNumber); // check that it's a number.
          resource.setMaxNumberOfEntries(maxNumber);
          resource.setUnsaved();
        }
        catch (NumberFormatException ex)
        {
//        do nothing... // TODO display error message?
        }
    }
  }

  private void updateDisplayImage(Request req, NewsFeedResource resource)
  {
      if (req.getParameter("image") != null && !resource.isDisplayImage())
      {
          resource.setDisplayImage(true);
          resource.setUnsaved();
      }
      else if (req.getParameter("image") == null && resource.isDisplayImage())
      {
          resource.setDisplayImage(false);
          resource.setUnsaved();
      }
  }
  
  private void updateDisplayTitle(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("title") != null && !resource.isDisplayTitle())
    {
      resource.setDisplayTitle(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("title") == null && resource.isDisplayTitle())
    {
      resource.setDisplayTitle(false);
      resource.setUnsaved();
    }
  }
  
  private void updateDisplayDescription(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("description") != null && !resource.isDisplayDescription())
    {
      resource.setDisplayDescription(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("description") == null && resource.isDisplayDescription())
    {
      resource.setDisplayDescription(false);
      resource.setUnsaved();
    }
  }

  private void updateDisplayAuthor(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("author") != null && !resource.isDisplayAuthor())
    {
      resource.setDisplayAuthor(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("author") == null && resource.isDisplayAuthor())
    {
      resource.setDisplayAuthor(false);
      resource.setUnsaved();
    }
  }

  private void updateAllowTitleLinks(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("allowlinks") != null && !resource.isAllowTitleLinks())
    {
      resource.setAllowTitleLinks(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("allowlinks") == null && resource.isAllowTitleLinks())
    {
      resource.setAllowTitleLinks(false);
      resource.setUnsaved();
    }
  }
  
  private void updateDisplayDate(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("date") != null && !resource.isDisplayDate())
    {
      resource.setDisplayDate(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("date") == null && resource.isDisplayDate())
    {
      resource.setDisplayDate(false);
      resource.setUnsaved();
    }
  }

  private void updateDisplayItemTitles(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("itemtitles") != null && !resource.isDisplayEntryTitles())
    {
      resource.setDisplayEntryTitles(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("itemtitles") == null && resource.isDisplayEntryTitles())
    {
      resource.setDisplayEntryTitles(false);
      resource.setUnsaved();
    }
  }

  private void updateDisplayItemAuthors(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("itemauthors") != null && !resource.isDisplayEntryAuthors())
    {
      resource.setDisplayEntryAuthors(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("itemauthors") == null && resource.isDisplayEntryAuthors())
    {
      resource.setDisplayEntryAuthors(false);
      resource.setUnsaved();
    }
  }


  private void updateDisplayItemContent(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("content") != null && !resource.isDisplayEntryContent())
    {
      resource.setDisplayEntryContent(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("content") == null && resource.isDisplayEntryContent())
    {
      resource.setDisplayEntryContent(false);
      resource.setUnsaved();
    }
  }

  private void updateDisplayExcerpt(Request req, NewsFeedResource resource)
    {
      if (req.getParameter("excerpt") != null && !resource.isDisplayExcerpt())
      {
        resource.setDisplayExcerpt(true);
        resource.setUnsaved();
      }
      else if (req.getParameter("excerpt") == null && resource.isDisplayExcerpt())
      {
        resource.setDisplayExcerpt(false);
        resource.setUnsaved();
      }
    }

  private void updateDisplayItemDate(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("date") != null && !resource.isDisplayEntryDate())
    {
      resource.setDisplayEntryDate(true);
      resource.setUnsaved();
    }
    else if (req.getParameter("date") == null && resource.isDisplayEntryDate())
    {
      resource.setDisplayEntryDate(false);
      resource.setUnsaved();
    }
  }

  private void updateItemSeparationTag(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("separationtag") != null)
    {
      String separationTag = req.getParameter("separationtag");
      if (!separationTag.equals(resource.getEntrySeparationTag()))
      {
      resource.setEntrySeparationTag(separationTag);
      resource.setUnsaved();
      }
    }
  }
  private void updateFeedURL(Request req, NewsFeedResource resource)
  {
    if (req.getParameter("newsfeedURL") != null)
    {
      String url = req.getParameter("newsfeedURL");
      if (!url.equals(resource.getFeedURL()))
      {
      resource.setFeedURL(url);
      resource.setUnsaved();
      }
    }
  }

  protected void resourceMenuItem(Resource resource, Request breq, PrintWriter out, ResourceMenuOutputState state, int depth, int highlight)
      throws IOException, BuildingServerException
  {
      NewsFeedResource newsfeed = (NewsFeedResource)resource;
    if ( newsfeed.isDisplayInline() )
      displayInline( newsfeed, breq, out, state, depth, highlight );
    else
      displayLinked( newsfeed, breq, out, state, depth, highlight );
  }

  private void displayInline(NewsFeedResource resource, Request breq, PrintWriter out, ResourceMenuOutputState state, int depth, int highlight)
      throws IOException, BuildingServerException
  {
    boolean manage;
    int level;
    String href, target, content;

    content = transformFeed( resource );

    manage = resource.checkPermission( Permission.MANAGE );
    href = ( !state.rootless && depth==1  )?null:
        ( breq.getContextPath() +breq.getServletPath() + resource.getFullName() );
    target = "_top";


//    if ( !resource.checkPermission( Permission.VIEW ) )
//    {

      level = ( (depth - 1) % 10) + 1;

      // span is used to get everything on one line in browsers that
      // lack CSS but CSS redfines as block.
      out.print("<span class=\"" + state.css_class_prefix + "_node_content");
      if (depth == 1)
        out.print("_without_stalk");
      out.print("_lev");
      out.print(level);
      out.print("_hl");
      out.print(highlight);
      out.print("\">");

      if (href != null && manage) {
        out.print("<a");
        if (target != null) {
          out.print(" target=\"");
          out.print(target);
          out.print("\"");
        }
        out.print(" href=\"");
        out.print(href);
        out.print("\" alt=\"Manage NewsFeed.\">  &gt;</a>");
      }

      out.print(content);
// TODO Do we want to have timed release?
//              openDate = resource.getOpenDate();
//              closeDate = resource.getCloseDate();
//              if (! (openDate == null && closeDate == null)) {
//                available_date = "<br>This resource is available";
//                if (openDate != null)
//                  available_date += " from " +
//                      org.bodington.util.DateFormatter.formatDate(openDate, 2);
//                if (closeDate != null)
//                  available_date += " until " +
//                      org.bodington.util.DateFormatter.formatDate(closeDate, 2);
//
//                out.println(available_date);
//              }

      out.print("</span>");

  }

  private void displayLinked(Resource resource, Request breq, PrintWriter out, ResourceMenuOutputState state, int depth, int highlight)
      throws IOException, BuildingServerException
  {
    Facility facility;
    Template template;
    String href=null, manage_href, icon_src=null, title=null, target=null, manage_target, content;
    boolean italic=false;  // should really use a redefinable style

    boolean manage = false;
    boolean deny = false;

    java.util.Date openDate, closeDate;
    String available_date;

    manage = resource.checkPermission( Permission.MANAGE );
    href = ( !state.rootless && depth==1  )?null:
        ( breq.getContextPath() +breq.getServletPath() + resource.getFullName() );
    target = "_top";
    
    manage_href = href + "bs_template_manage.html";
    manage_target = "menu";
    
    // using getTemplateGifUrl doesn't work for descendant resources - need to
    // reference proper resource.
    facility = state.fl.get( new Integer( resource.getHttpFacilityNo() ) );
    if ( facility!=null )
    {
      template = Template.get( facility.facilityname, resource.getImplicitHttpUIStyle(), resource.getResourceId(), state.big_icons?"icon.gif":"iconsmall.gif" );
      if ( template != null )
        icon_src = breq.getContextPath() + state.gif_url + template.getUrl() + state.colour_code;
    }
    title = resource.getTitle();
    if ( !resource.checkPermission( Permission.VIEW ) )
    {
      if ( state.anon )
        // anonymous users are allowed to see link because
        // they get a message about logging in if they enter
        italic=true;
      else
      {
        // logged in but no access - don't give link
        href=null;
        deny = true;
      }
    }

    // heading level for title line matches depth but there are only
    // six heading levels in HTML so stop there.
    int hlevel = (depth > 6) ? 6 : depth;
    int level = ( (depth - 1) % 10) + 1;

    // title in heading with appropriate class attribute
    out.print("          <h");
    out.print(hlevel);

    out.print(" class=\"" + state.css_class_prefix + "_node_title_lev");
    out.print(level);
    out.print("\">");

    // optional link around whole title (inc. icon)
    // changed to 2 separate links for icon and text
    // (and a third for the manage link)

    if (href != null) {
      out.print("<a");
      if (target != null) {
        out.print(" target=\"");
        out.print(target);
        out.print("\"");
      }
      out.print(" href=\"");
      out.print(href);
      out.print("\">");
    }

    out.print("<img alt=\"Icon for a " + resource.getResourceTypeName() + ".\" src=\"");
    out.print(icon_src);
    out.print("\" ");

    if (depth == 1)
      out.print("class=\"" + state.css_class_prefix +
                "_node_icon_without_stalk\" />");
    else
      out.print("class=\"" + state.css_class_prefix +
                "_node_icon_no_expander\" />");

    if (href != null)
      out.print( "</a>" ); // closing tag for icon link

      // span is used to get everything on one line in browsers that
      // lack CSS but CSS redfines as block.
    out.print("<span class=\"" + state.css_class_prefix + "_node_content");
    if (depth == 1)
      out.print("_without_stalk");
    out.print("_lev");
    out.print(level);
    out.print("_hl");
    out.print(highlight);
    out.print("\">");

    if (href != null) {
      out.print("<a"); // tag for text link
      if (target != null) {
        out.print(" target=\"");
        out.print(target);
        out.print("\"");
      }
      out.print(" href=\"");
      out.print(href);
      out.print("\">");
    }


    if (italic)
      out.print("<i>");

    if (title != null)
      out.print(title);
    else
    {
    if (href != null)
      out.print(href);
    else
      out.print("{untitled item}");
    }

    if (italic)
      out.print("</i>");

    if (href != null)
      out.print( "</a>" ); // closing tag for text link

    if (href != null && manage) {
      out.print("&nbsp;<a"); // tag for manage link
      if (target != null) {
        out.print(" target=\"");
        out.print(manage_target);
        out.print("\"");
      }
      out.print(" href=\"");
      out.print(manage_href);
      out.print("\" alt=\"Manage NewsFeed.\">  &gt;</a>"); // closing tag for manage link
    }

    out.print("</span>");

    out.print("</h"); // end of node_title
    out.print(hlevel);
    out.println(">");

        if (!state.rootless && depth == 1)
          content = resource.getIntroduction();
        else
          content = resource.getDescription();
        if (deny)
    {
      content = "<em>"
          + "You are not included on the access list for this item.</em>"
          + " <br />"
          + content;
      }

    content = (content == null) ? "" : content;

        out.print("<div class=\"" + state.css_class_prefix + "_node_content");
        if (depth == 1)
          out.print("_without_stalk");
        out.print("_lev");
        out.print(level);
        out.print("_hl");
        out.print(highlight);
        out.print("\">");

        out.print(content);

        openDate = resource.getOpenDate();
        closeDate = resource.getCloseDate();

    if (! (openDate == null && closeDate == null))
    {
      available_date = "This resource is available";
          if (openDate != null)
      {
        available_date += " from "
            + org.bodington.util.DateFormatter.formatDate(openDate, 2);
      }
          if (closeDate != null)
      {
        available_date += " until "
            + org.bodington.util.DateFormatter.formatDate(closeDate, 2);
      }
      out.print("<div>");
          out.println(available_date);
      out.print("</div>");
        }

        out.print("</div>");
//    out.print( "<div class=\"clearer\">&nbsp;</div>\n");
      }

    private String getFrameDisplay(NewsFeedResource resource)
    {
        if (resource.isDisplayInline())
        { // TODO keep this? (loads manage page instead of displaying blank
          // page...)
            String redirect = "<SCRIPT LANGUAGE=JavaScript>"
                + "top.buildmain.feed.location.href=\"./bs_template_manage.html\""
                + "</SCRIPT>";
            return redirect;
        }

        return transformFeed( resource );
    }

    public String transformFeed(NewsFeedResource resource)
    { 
        // Displays XML feed transformed to HTML.
        // If a problem occurs, and display is set to:
        // inline - nothing displayed at all.
        // not inline - an error message is displayed.
        
        URL url;
        HttpURLConnection httpConn;
        Document doc;
        Hashtable paramMap;
        
        try
        {
            url = new URL( resource.getFeedURL());
            
            if ( denyAccess( url ) )
            {
                if ( resource.isDisplayInline() )
                    return "";
                return "The URL you have tried to access is restricted.";
            }
                
            httpConn = (HttpURLConnection) url.openConnection();
            doc = DOMFactory.parse(httpConn.getInputStream());
            
            paramMap = resource.loadTransformParams();
            StringWriter writer = new StringWriter();
            // TODO Should be able to use a re-useable template
            // instead of loading the stylesheet every time, but it doesn't work...

//            root = XMLTransformer.transform(paramMap, root, stylesheetTemplate);
//            XMLSerializer.out(root, "html", writer);
            InputStream stylesheet = getClass().getResourceAsStream(TRANSFORM_STYLESHEET);
//            URL stylesheet = getClass().getResource(TRANSFORM_STYLESHEET);
            XMLSerializer.transformOutput(doc, stylesheet, paramMap, writer);
            
            return writer.toString();
            
        }
        catch (MalformedURLException ex)
        {
            setStatusMessage("The URL for the news feed is malformed."
                + ex.getMessage());
        }
        catch (JaferException ex)
        {
            setStatusMessage("Error in parsing/transforming XML to HTML."
                + ex.getMessage());
        }
        catch (IOException ex)
        {
            setStatusMessage("Error in connecting to news feed server, or accessing newsfeed."
                + ex.getMessage());
        }

        Logger.getLogger("org.bodington.server").severe(getStatusMessage());
        
        if (!resource.isDisplayInline())
            return getStatusMessage();

        return "";
    }

    // Original intention was that the status message would only be displayed
    // when the user requested it from the user interface.

    private String getStatusMessage()
    {
        if (statusMessage != null)
            return statusMessage;

        return "No status message available.";
    }

    private void setStatusMessage(String message)
    {
        if (message != null)
            statusMessage = message;
    }
    private boolean denyAccess( URL url )
    {
        User user = (User)BuildingContext.getContext().getUser();
        String username = user.getInitials();
        String privateStem = "hcdt1.oucs.ox.ac.uk/pebble/";
        String host = url.getHost();
        String path = url.getPath();
        
        if ( (host + path).indexOf(privateStem) >= 0 )
        {
            if ( path.indexOf(username) >= 0 )
                return false;
            else
                return true;
        }
        return false;
    }
    
  private void createStylesheetTemplate(String stylesheetPath)
        throws JaferException
    {
        InputStream stylesheet = getClass().getResourceAsStream(stylesheetPath);
        stylesheetTemplate = XMLTransformer.createTemplate(stylesheet);
    }
}
