/*
 * ====================================================================== 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 java.io.PrintWriter;
import java.io.IOException;
import javax.servlet.ServletException;
import org.bodington.servlet.template.Template;

import java.util.logging.*;
import org.bodington.server.resources.Resource;
import org.bodington.server.resources.BlogResource;
import org.bodington.server.BuildingServerException;
import org.bodington.server.BuildingContext;
import org.bodington.server.realm.Permission;

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.util.Hashtable;

public class BlogFacility extends Facility
{

    private static String TRANSFORM_STYLESHEET = "/org/bodington/xsl/feedTransform.xsl";
    private Templates stylesheetTemplate;
    private String statusMessage;

    public BlogFacility() 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 BlogResource();
        }
        catch (BuildingServerException ex)
        { // TODO ??
            return null;
        }
    }

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

        if (!(new_resource instanceof BlogResource))
            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("blogURL") != null)
        {
            url = breq.getParameter("blogURL");
            ((BlogResource) new_resource).setBlogURL(url);

            return true;
        }
        return false;
    }

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

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

        BlogResource resource = (BlogResource) 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);
                updateBlogURL(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,
        BlogResource 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.isDisplayEntryContent())
                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("blogURL"))
        {
            out.print(resource.getBlogURL());
            return true;
        }

        return false;
    }

    private void updateDisplayInline(Request req, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource 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, BlogResource resource)
    {
        if (req.getParameter("separationtag") != null)
        {
            String separationTag = req.getParameter("separationtag");
            if (!separationTag.equals(resource.getEntrySeparationTag()))
            {
                resource.setEntrySeparationTag(separationTag);
                resource.setUnsaved();
            }
        }
    }

    private void updateBlogURL(Request req, BlogResource resource)
    {
        if (req.getParameter("blogURL") != null)
        {
            String url = req.getParameter("blogURL");
            if (!url.equals(resource.getBlogURL()))
            {
                resource.setBlogURL(url);
                resource.setUnsaved();
            }
        }
    }

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

    private void displayInline(BlogResource 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 ) ) // else : just
        // don't see it at all!
        //    {

        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 Blog.\">&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"); // link for icon
            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 Blog.\">&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(BlogResource 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(BlogResource 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.getBlogURL());

            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);
    }
}