/* ======================================================================
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 java.util.logging.*;


import org.bodington.servlet.*;

import java.io.*;
import java.sql.*;
import java.util.*;
import java.rmi.RemoteException;
import javax.servlet.*;
import javax.servlet.http.*;

import org.bodington.database.PrimaryKey;
import org.bodington.server.*;
import org.bodington.server.realm.User;
import org.bodington.server.resources.Resource;
import org.bodington.server.events.Event;
import org.bodington.server.events.OpinionEvent;
import org.bodington.assessment.*;

public class QuestionnaireFacility extends org.bodington.servlet.facilities.Facility
	{
	
	static final int EVENT_START        =0;
	static final int EVENT_RECORD  =1;


	public String defaultIcon()
		{
		return "questionnaire.gif";
		}
	public String defaultSmallIcon()
		{
		return "questionnaire-small.gif";
		}


    /**
     * Facility subclasses can refuse copying of resources.
     * @return True if resources that use this facility can be copied.
     */
    public boolean canCopy( Resource resource )
    {
        return true;
    }
    
	public Resource newResource()
		{
		return new Questionnaire();
		}
	
	
	public boolean initResource( Request breq, Resource new_resource )
		throws Exception
		{
		Questionnaire questionnaire;

		if ( !(new_resource instanceof Questionnaire) )
			throw new Exception( "Technical problem: An incorrect type of resource was created." );
		
		questionnaire = (Questionnaire)new_resource;
		questionnaire.setFlags( 0 );

		return true;
		}


    /**
     * Use the properties of an existing Resource to initialise a newly created Resource. <p>
     * <i>(WebLearn modification (method added): 02/12/2003 Colin Tatham)</i>
     * @param original_resource The resource with properties to copy.
     * @param new_resource The resource to initialise.
     * @return True if initialisation was OK.
     * @exception BuildingServerException Thrown if there is any problem initialising the resource.
     *
     */
	public boolean initResource( Resource original_resource, Resource new_resource )
		throws BuildingServerException
		{
		 if ( !(new_resource instanceof Questionnaire) )
		   throw new BuildingServerException( "Error: The wrong type of resource was created." );

		 Questionnaire original = (Questionnaire)original_resource;
		 Questionnaire new_q = (Questionnaire)new_resource;

		 new_q.setQuestionnaireFlags(original.getQuestionnaireFlags());

		 return true;
	}


    /**
     * Copy the content of an existing Resource to another Resource. 
     * Content may be authored content or user data, and varies according to the resource type:<br />
     * Questionnaire<br />
     * authored : questions, statements<br />
     * userdata : answers (Not implemented.) <p>
     * <i>(WebLearn modification (method added): 02/12/2003 Colin Tatham)</i>
     * @param original_resource The resource with content to copy.
     * @param new_resource The resource to copy content to.
     * @param breq The building HTTP request, which is used to determine which type of content to copy.
     * @exception BuildingServerException Thrown if there is any problem copying the resource content.
     *
     */
	public void copyContent( Resource original_resource, Resource new_resource, Request breq )
		 throws BuildingServerException
	        {
//	  authored : questions, statements
//	  userdata : answers? /** @todo  */

	         BuildingSession session = BuildingSessionManagerImpl.getSession( original_resource );
		 if ( !(session instanceof QuestionnaireSession) )
		   throw new BuildingServerException( "Unable to access appropriate resource session." );

		 try
		 {
		   if ( breq.getParameter( "authored" ) != null )
		   {
		     copyAuthoredContent( original_resource, new_resource );
//		     if ( breq.getParameter( "userdata" ) != null )
//		       copyUserContent( original_resource, new_resource );
		   }
		 }
		 catch (Exception ex)
		 {
		   throw new BuildingServerException( ex.getMessage() );
		 }
	}


    /**
     * Copy the authored content of an existing Resource to another Resource. <p>
     * <i>(WebLearn modification (method added): 02/12/2003 Colin Tatham)</i>
     * @param original_resource The resource with content to copy.
     * @param new_resource The resource to copy content to.
     * @exception BuildingServerException Thrown if there is any problem copying the resource content.
     * @exception RemoteException Thrown if there is any problem copying the resource content.
     *
     */
	private void copyAuthoredContent( Resource original_resource, Resource new_resource )
		throws BuildingServerException, RemoteException
		{
		 QuestionnaireSession session;
		 Vector questions;
		 QuestionnaireQuestion orig_question, new_question;

		 session = (QuestionnaireSession)BuildingSessionManagerImpl.getSession( original_resource );
		 questions = ((QuestionnaireSession)session).getQuestionnaireQuestionsInOrder();

		 for (int i=0; i<questions.size(); i++ )
		 {
		   orig_question = (QuestionnaireQuestion)questions.elementAt( i );
		   new_question = new QuestionnaireQuestion();
		   new_question.setResourceId( new_resource.getResourceId() );
		   /** @todo report possible bug: */
		   new_question.setStandardQuestion( true ); // sets all statements to empty string
		   new_question.setStandardQuestion( orig_question.isStandardQuestion() );
		   new_question.setCanComment( orig_question.canComment() );
		   new_question.setIntroduction( orig_question.getIntroduction() );
		   new_question.setOrdinal( orig_question.getOrdinal() );
		   new_question.setFlags( orig_question.getFlags() );
		   for ( int n=0; n<orig_question.getStatementCount(); n++ )
		     new_question.setStatement( n, orig_question.getStatement(n) );

		   new_question.save();
		 }
		}


	public boolean createCheck( Request breq, PrintWriter out )
		{
		return true;
		}
	

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

		try
			{
			BuildingSession session;
			QuestionnaireSession q_session;

		    session = BuildingSessionManagerImpl.getSession( req.getResource() );
		    if ( !(session instanceof QuestionnaireSession) )
		    	{
		    	out.println( "<HR>Technical problem: unable to access appropriate tool session.<HR>" );
		    	return;
		    	}
		    q_session = (QuestionnaireSession)session;

		

			if ( command.equalsIgnoreCase( "qpaper" ) ||
		    	command.equalsIgnoreCase( "qsummary" ) ||
		    	command.equalsIgnoreCase( "qcomments" ) ||
		    	command.equalsIgnoreCase( "qrecord" ) ||
		    	command.equalsIgnoreCase( "qitemedit" ) ||
		    	command.equalsIgnoreCase( "qeditqconfirm" ) ||
		    	command.equalsIgnoreCase( "qdeleteq" ) ||
		    	command.equalsIgnoreCase( "qrunbutton" ) ||
		    	command.equalsIgnoreCase( "qnewq" ) ||
		    	command.equalsIgnoreCase( "export" ) ||
		    	command.equalsIgnoreCase( "import" )	)
				{

				if ( out==null )
					return;

				if ( command.equalsIgnoreCase( "qpaper" ) )
					qprintpaper( req, out, q_session, insertname );
				if ( command.equalsIgnoreCase( "qsummary" ) )
					qprintsummary( req, out, q_session );
				if ( command.equalsIgnoreCase( "qcomments" ) )
					qprintqcomments( req, out, q_session );

				if ( command.equalsIgnoreCase( "qrecord" ) )
					qrecord( req, out, q_session, insertname );

				if ( command.equalsIgnoreCase( "qnewq" ) )
					qnewq( req, out, q_session, insertname );

				if ( command.equalsIgnoreCase( "qitemedit" ) )
					qitemedit( req, out, q_session, insertname );

				if ( command.equalsIgnoreCase( "qeditqconfirm" ) )
					qeditqconfirm( req, out, q_session, insertname );

				if ( command.equalsIgnoreCase( "qdeleteq" ) )
					qdeleteq( req, out, q_session );

				if ( command.equalsIgnoreCase( "qrunbutton" ) )
					qrunbutton( req, out, q_session );
				
				if ( command.equalsIgnoreCase( "export" ) )
					export( req, out, q_session );
				
				if ( command.equalsIgnoreCase( "import" ) )
					importq( req, out, q_session );
				
				return;
				}
			}		
		catch ( BuildingServerException bsex )
			{
			logException( out, "QuestionnaireFacility", "insert", 
			    "Technical error processing page.",
			    bsex );
			return;
			}
		
		
		super.insert( req, out, command, insertname );
		}



	
	private void questionToHTML( QuestionnaireQuestion question, QuestionnaireResponse response, QuestionnaireAnalysis q_analysis, PrintWriter out, String style )
		throws IOException, BuildingServerException
		{
		char letter;
		int i, j, n, total, max;
		int[] counts;
		double scale;
		boolean answer[]=new boolean[10];
		String statement[]=new String[10];
		Vector comments;
		
		out.println( "<TR><TD COLSPAN=3>" );
		if ( style.equalsIgnoreCase( "run" ) )
			{
			out.println( "<INPUT TYPE=HIDDEN VALUE=TRUE NAME=Q" + question.getQuestionnaireQuestionId() + ">" );
			}
		out.println( question.getIntroduction() );
		out.println( "</TD></TR>" );

		n = question.getStatementCount();
		counts = new int[n];
		total=0;
		max=0;
		for ( i=0; i<n; i++ )
			{
			letter=(char)('A'+i);
			if ( style.equalsIgnoreCase( "run" ) )
				{
				out.println( "<TR><TD VALIGN=TOP WIDTH=20><B>" );
				out.println( letter );
				out.println( "</B></TD><TD VALIGN=TOP WIDTH=20>" );
				out.print( "<INPUT TYPE=RADIO " );
				out.print( "NAME=QR" );
				out.print( question.getQuestionnaireQuestionId().toString() );
				out.print( " VALUE=" + letter );
				if ( response != null && response.getItem() == i )
					out.print( " CHECKED>" );
				else
					out.print( ">" );
				out.println( "</TD><TD VALIGN=TOP WIDTH=1000>" );
				out.println( question.getStatement( i ) );
				out.println( "</TD></TR>" );
				}
			else
				{
				out.println( "<TR><TD VALIGN=TOP WIDTH=20><B>" );
				out.println( letter );
				out.println( "</B></TD>" );
				if ( q_analysis != null )
					{
					counts[i] = q_analysis.getItemCounts( question.getQuestionnaireQuestionId(), i );
					out.print( "<TD WIDTH=20>" );
					out.print( counts[i] );
					out.print( "</TD>" );
					total+=counts[i];
					if ( counts[i]>max ) max=counts[i];
					}
				out.println( "<TD VALIGN=TOP WIDTH=1000>" );
				out.println( question.getStatement( i ) );
				out.println( "</TD></TR>" );
				if ( q_analysis != null )
					{
					comments = q_analysis.getComments( question.getQuestionnaireQuestionId(), i );
					for ( j=0; j< comments.size(); j++ )
						{
						out.print( "<TR><TD COLSPAN=2></TD><TD><BLOCKQUOTE>" );
						out.print( (String)comments.elementAt( j ) );
						out.println( "</BLOCKQUOTE></TD></TR>" );
						}
					}
				}
			}

		if ( q_analysis != null )
			{
			if ( question.isStandardQuestion() )
				{
				if ( (counts[0]+counts[1])>max ) max=counts[0]+counts[1];
				if ( (counts[3]+counts[4])>max ) max=counts[3]+counts[4];
				}
				
			if ( max<10 ) scale=25.0;
			else scale=250.0/max;
			out.println( "<TR><TD COLSPAN=3>" );
			if ( question.isStandardQuestion() )
				{
				out.println( "<TABLE BORDER><TR><TD WIDTH=75>Agree</TD>" );
				if ( (int)(scale*counts[1]) > 0 )
					out.println( "<TD BGCOLOR=GREEN WIDTH=" + (int)(scale*counts[1]) + ">.</TD>" );
				if ( (int)(scale*counts[0]) > 0 )
					out.println( "<TD BGCOLOR=RED WIDTH=" + (int)(scale*counts[0]) + ">.</TD>" );
				out.println( "</TR></TABLE>" );
				out.println( "<TABLE BORDER><TR><TD WIDTH=75>Neutral</TD>" );
				if ( (int)(scale*counts[2]) > 0 )
					out.println( "<TD BGCOLOR=GREEN WIDTH=" + (int)(scale*counts[2]) + ">.</TD>" );
				out.println( "</TR></TABLE>" );
				out.println( "<TABLE BORDER><TR><TD WIDTH=75>Disagree</TD>" );
				if ( (int)(scale*counts[3]) > 0 )
					out.println( "<TD BGCOLOR=GREEN WIDTH=" + (int)(scale*counts[3]) + ">.</TD>" );
				if ( (int)(scale*counts[4]) > 0 )
					out.println( "<TD BGCOLOR=RED WIDTH=" + (int)(scale*counts[4]) + ">.</TD>" );
				out.println( "</TR></TABLE>" );
				}
			else
				{
				for ( i=0; i<n; i++ )
					{
					letter=(char)('A'+i);
					out.println( "<TABLE BORDER><TR><TD WIDTH=30><B>" + letter + "</B></TD>" );
					if ( (int)(scale*counts[i]) > 0 )
						out.println( "<TD BGCOLOR=GREEN WIDTH=" + (int)(scale*counts[i]) + ">.</TD>" );
					out.println( "</TR></TABLE>" );
					}
				}
			out.println( "</TD></TR>" );
			
			
			
			comments = q_analysis.getComments( question.getQuestionnaireQuestionId(), 10 );
			for ( j=0; j< comments.size(); j++ )
				{
				if ( n>0 && j==0 )
					out.print( "<TR><TD COLSPAN=3>Comments from people who didn't select an option.</TD></TR>" );

				out.print( "<TR><TD COLSPAN=2></TD><TD><BLOCKQUOTE>" );
				out.print( (String)comments.elementAt( j ) );
				out.println( "</BLOCKQUOTE></TD></TR>" );
				}
			}

		if ( style.equalsIgnoreCase( "run" ) )
			{
			if ( n>0 )
				{
				out.println( "<TR><TD VALIGN=TOP WIDTH=20></TD><TD VALIGN=TOP WIDTH=20>" );
				out.print( "<INPUT TYPE=RADIO " );
				out.println( "NAME=QR" + question.getQuestionnaireQuestionId() + " VALUE=X>" );
				out.println( "</TD><TD VALIGN=TOP WIDTH=1000>Cancel selection.</TD></TR>" );
				}
			if ( question.canComment() )
				{
				out.print( "<TR>" );
				out.print( "<TD COLSPAN=3><SPAN CLASS=bs-textarea><TEXTAREA ROWS=6 COLS=40 NAME=QC" );
				out.print( question.getQuestionnaireQuestionId().toString() );
				out.print( ">" );
				if ( response != null && response.getComment() != null )
					out.print( response.getComment() );
				out.println( "</TEXTAREA></SPAN></TD></TR>" );
				}
			}
		
		if ( style.equalsIgnoreCase( "view" ) && response!=null )
			{
			out.print( "<TR><TD COLSPAN=3>" );
			if ( n>0 )
				{
				if ( response.getItem()<10 )
					out.println( "You selected " + (char)('A' + response.getItem()) + "." );
				else
					out.println( "You haven't selected any item for this question." );
				}
			if ( question.canComment() && response.getComment() != null && response.getComment().length()>0 )
				{
				out.println( "You entered this comment;<BLOCKQUOTE>" );
				out.print( response.getComment() );
				out.println( "</BLOCKQUOTE>" );
				}
			}

		}
	



	private void qprintpaper( Request req, PrintWriter out, QuestionnaireSession q_session, String insertname )
		throws IOException, BuildingServerException
		{
		int i;
		
		Vector questions_in_order;
		QuestionnaireQuestion q;
		QuestionnaireResult result=null;
		QuestionnaireResponse response=null;
		QuestionnaireAnalysis analysis=null;
		Hashtable responses = null;
		Resource resource;
		User user;
		
		resource = BuildingContext.getContext().getResource();
		user = (User)BuildingContext.getContext().getUser();
		questions_in_order = q_session.getQuestionnaireQuestionsInOrder();
			
			
		if ( insertname.equalsIgnoreCase( "analysis" ) )
			{
			analysis =  new QuestionnaireAnalysis();
			q_session.analyse( null, analysis );
			}
				
		if ( insertname.equalsIgnoreCase( "run" ) || insertname.equalsIgnoreCase( "view" ) )
			{
			result = q_session.getQuestionnaireResult();
			
			if ( result!=null )
				responses=q_session.getQuestionnaireResponses( result.getQuestionnaireResultId() );
				
			if ( responses==null )
				responses = new Hashtable();
			}
			
		if ( insertname.equalsIgnoreCase( "run" ) )
			{
			out.println( "<FORM METHOD=POST ACTION=bs_template_qrecord.html>" );
			}
			
		for ( i=0; i<questions_in_order.size(); i++ )
			{
			q=(QuestionnaireQuestion)questions_in_order.elementAt( i );

			if ( responses==null )
				response = null;
			else
				response = (QuestionnaireResponse)responses.get( q.getQuestionnaireQuestionId() );
				
			if ( insertname.equalsIgnoreCase( "edit" ) )
				{
				out.println( "<P></P><TABLE BORDER><TR><TD COLSPAN=2><H4>Question " + 
					(i+1) + " (" + q.getOrdinal() + ")</H4></TD>" );
				out.print( "<TD ALIGN=CENTER><FORM METHOD=POST ACTION=\"" );
				out.print( req.getContextPath() );
				out.print( req.getServletPath() );
				out.print( resource.getFullName()  );
				out.print( q.getQuestionnaireQuestionId() + "/bs_template_qeditq.html\">" );
				out.println( "<INPUT TYPE=SUBMIT VALUE=\"Edit This Question\"></FORM></TD></TR>" );
				}
			else
				{
				out.println( "<HR><TABLE><TR><TD COLSPAN=3><H4>Question " + (i+1) + "</H4></TD></TR>" );
				}
				
			questionToHTML( q, response, analysis, out, insertname );
				
			out.println( "</TABLE>" );
			}

		if ( i==0 )
			out.println( "<P>There are currently no questions in this questionnaire.</P>" );
		else
			{
			if ( insertname.equalsIgnoreCase( "run" ) )
				{
				out.println( "<P><INPUT TYPE=SUBMIT VALUE=\"Record Answers Now\"></FORM></P>" );
        		Event event = new OpinionEvent( 
        						OpinionEvent.EVENT_START,
        						req.getResource().getResourceId(), 
        						user.getUserId(), 
    	    					null );
	        	event.save();
				}
			}
		
		
		}

	private void qitemedit(  Request req, PrintWriter out, QuestionnaireSession q_session, String insertname )
		throws IOException, BuildingServerException
		{
		String id, field, statement;
		PrimaryKey qid;
		Hashtable questions;
		QuestionnaireQuestion q;
		
		if ( !BuildingContext.getContext().checkPermission( "edit" ) )
			{
			out.println( "<PRE>You don't have permission to edit questions in this location of the building.</PRE>\n" );
			return;
			}


		//must have an id in the parameter part of the URL
		if ( req.getTemplateParameterCount() < 1 )
			{
			out.println( "<I>Can't display edit field.</I>" );
			return;
			}
		id=(String)req.getTemplateParameter( 0 );
		qid= new PrimaryKey( Integer.parseInt( id ) );

		
		questions = q_session.getQuestionnaireQuestions();
		q=(QuestionnaireQuestion)questions.get( qid );
		
		if ( q==null )
			{
			out.println( "<I>Can't display edit field.</I>" );
			return;
			}

		if ( insertname.equalsIgnoreCase( "ordinal" ) )
			{
			out.println( "<INPUT NAME=ordinal VALUE=\"" +q.getOrdinal() + "\">" );
			return;
			}
		if ( insertname.equalsIgnoreCase( "statements" ) )
			{
			out.println( "<INPUT NAME=statements VALUE=\"" +q.getStatementCount() + "\">" );
			return;
			}
		if ( insertname.equalsIgnoreCase( "introduction" ) )
			{
			out.print( "<SPAN CLASS=bs-textarea><TEXTAREA NAME=introduction COLS=45 ROWS=8>" );
			out.print( q.getIntroduction() );
			out.println( "</TEXTAREA></SPAN>" );
			return;
			}

		for ( int i=0; i<10; i++ )
			{
			field = "statement_" + (char)('a' + i );
			statement = q.getStatement( i );
			if ( insertname.equalsIgnoreCase( field ) )
				{
				out.print( "<SPAN CLASS=bs-textarea><TEXTAREA NAME=" );
				out.print( field );
				out.print( " COLS=30 ROWS=4>" );
				out.print( statement==null?"":statement );
				out.println( "</TEXTAREA></SPAN>" );
				return;
				}
			}

		if ( insertname.equalsIgnoreCase( "is_standard" ) )
			{
			out.print( "<INPUT TYPE=CHECKBOX NAME=is_standard VALUE=true ONCLICK=standardise() " );
			out.println( q.isStandardQuestion()?"CHECKED>":">" );
			return;
			}

		if ( insertname.equalsIgnoreCase( "can_comment" ) )
			{
			out.print( "<INPUT TYPE=CHECKBOX NAME=can_comment VALUE=true " );
			out.println( q.canComment()?"CHECKED>":">" );
			return;
			}
		}

	
	private void qeditqconfirm(  Request req, PrintWriter out, QuestionnaireSession q_session, String insertname )
		throws IOException, BuildingServerException
		{
		int n;
		String id, param;
		PrimaryKey qid;
		Hashtable questions;
		QuestionnaireQuestion q;
		
		if ( !BuildingContext.getContext().checkPermission( "edit" ) )
			{
			out.println( "<PRE>You don't have permission to edit questions in this location of the building.</PRE>\n" );
			return;
			}


		//must have an id in the parameter part of the URL
		if ( req.getTemplateParameterCount() < 1 )
			{
			out.println( "<I>Can't display edit field.</I>" );
			return;
			}
		id=(String)req.getTemplateParameter( 0 );
		qid= new PrimaryKey( Integer.parseInt( id ) );

		
		questions = q_session.getQuestionnaireQuestions();
		q=(QuestionnaireQuestion)questions.get( qid );

		if ( q==null )
			{
			out.println( "<I>Can't display edit field.</I>" );
			return;
			}

		param=req.getParameter( "ordinal" );
		try
			{
			q.setOrdinal( Integer.parseInt( param ) );
			}
		catch ( NumberFormatException ex )
			{
			out.println( "<HR>Invalid number in ordinal field.<HR>" );
			return;
			}

		param = req.getParameter( "introduction" );
		if ( param==null ) param = "";
		q_session.changeQuestionText( q.getQuestionnaireQuestionId(), 
										q.getIntroductionBigStringId(), 
										param );
		for ( int i=0; i<10; i++ )
			{
			param = req.getParameter( "statement_" + (char)('a' + i) );
			if ( param==null ) param = "";
			q_session.changeQuestionText( q.getQuestionnaireQuestionId(), 
											q.getStatementBigStringId( i ), 
											param );
			}
											

		param=req.getParameter( "is_standard" );
		q.setStandardQuestion( param!=null && param.length()>0 );
		
		param=req.getParameter( "can_comment" );
		q.setCanComment( param!=null && param.length()>0 );

		q_session.changeQuestion( q.getQuestionnaireQuestionId(), q );

		out.println( "<HR>Question Saved<HR>" );
		}

	
	private void qnewq( Request req, PrintWriter out, QuestionnaireSession q_session, String insertname )
		throws IOException
		{
		try
			{
			q_session.createQuestion();
			}
		catch ( Exception ex )
			{
			out.println( "<HR>A technical problem occured while trying to create a new question.<HR>" + ex.getMessage() );
			}
		}	


	private void qdeleteq(  Request req, PrintWriter out, QuestionnaireSession q_session )
		throws IOException, BuildingServerException
		{
		int n;
		String id, param, notparam;
		PrimaryKey qid;

		if ( !BuildingContext.getContext().checkPermission( "edit" ) )
			{
			out.println( "<PRE>You don't have permission to delete (edit) questions in this location of the building.</PRE>\n" );
			return;
			}

		//must have an id in the parameter part of the URL
		if ( req.getTemplateParameterCount() < 1 )
			{
			out.println( "<I>Can't delete question.</I>" );
			return;
			}
		id=(String)req.getTemplateParameter( 0 );
		qid= new PrimaryKey( Integer.parseInt( id ) );

		
		param=req.getParameter( "confirm" );
		if ( param==null ) param="";
		notparam=req.getParameter( "notconfirm" );
		if ( notparam==null ) notparam="";
		if ( param.length()<1 || notparam.length()>0 )
			{
			out.println( "<HR>Wrong checkboxes selected - question not deleted.<HR>" );
			return;
			}

		q_session.removeQuestion( qid );
		}



	private void qprintsummary( Request req, PrintWriter out, QuestionnaireSession q_session )
		throws IOException
		{
		/*
		int i, lastqid;
		int tally[]=null;
		String sql;
		ResultSet results;
		Enumeration enum=questionnaire.getQuestions();
		QuestionnaireQuestion q;
		QuestionnaireSummary summary = new QuestionnaireSummary();
		Hashtable summarytable=new Hashtable();
		//java.util.Date d=new java.util.Date();

		Logger.getLogger("org.bodington").fine( "Questionnaire print paper A" );

		try
			{
			sql="SELECT question_id, item, COUNT(*) 'count' FROM " + DBObject.schema + "questionnaire_responses "+
				"WHERE result_id IN "+
 				"(SELECT result_id FROM " + DBObject.schema + "questionnaire_results WHERE location = " +
 				req.getResource().getResourceId().intValue() + ") " +
				"GROUP BY question_id, item "+
				"ORDER BY question_id, item	";
			
			results=db.select( sql );
			if ( results==null )
				{
				out.println( "<HR>Problem fetching results<HR>" );
				return;
				}
			
			lastqid=-1;
			//out.println( "<PRE>" );
			while ( results.next() )
				{
				//out.println( "Next record." );
				summary.load( results );
				//out.println( "Loaded." );
				//out.println( "qid: " + 
				//			 summary.question_id +
				//			 " item: " +
				//			 summary.item +
				//			 " count: " +
				//			 summary.count );
				
				if ( summary.question_id.intValue()!=lastqid )
					{
					tally=new int[10];
					for ( i=0; i<10; i++ )
						tally[i]=0;
					lastqid=summary.question_id.intValue();
					summarytable.put( summary.question_id, tally );
					}
				if ( summary.item!=null && summary.count!=null )
					if ( summary.item.intValue() >= 0 &&
						 summary.item.intValue() < 10 &&
						 summary.count.intValue() >= 0 )
						tally[summary.item.intValue()]=summary.count.intValue();
				}
			//out.println( "</PRE>" );
			}
		catch ( Exception ex )
			{
			out.println( "<HR>Problem fetching results<HR>" + ex );
			return;
			}

		Logger.getLogger("org.bodington").fine( "Questionnaire print paper B" );
		
		for ( i=0; enum.hasMoreElements(); i++ )
			{
			q=(QuestionnaireQuestion)enum.nextElement();
			tally=(int[])summarytable.get( q.question_id );
			out.println( "<HR><H4>Question " + (i+1) + "</H4>" );
			q.printSummary( "/icons/", out, tally );
			
			if ( BuildingContext.getContext().checkPermission( "manage" ) && q.can_comment )
				out.println( "<P><I><A HREF=\"" + 
							req.absoluteURL() + 
							q.question_id + 
							"/bs_template_qcomments.html\">Comments</A> were allowed " +
							"on this question.</I></P>" );
			
			}

		if ( i==0 )
			out.println( "<P>There are currently no questions in this questionnaire.</P>" );

		Logger.getLogger("org.bodington").fine( "Questionnaire print paper C" );
		*/
		}

	private void qprintqcomments( Request req, PrintWriter out, QuestionnaireSession q_session )
		throws IOException
		{
		/*
		int i, lastitem;
		String sql, id;
		Integer qid;
		ResultSet results;

		if ( !BuildingContext.getContext().checkPermission( "manage" ) )
			{
			out.println( "Sorry, you don't have sufficient access rights to see this information." );
			return;
			}

		//must have an id in the parameter part of the URL
		if ( req.getTemplateParameterCount() < 1 )
			{
			out.println( "<I>Invalid URL - no question ID included.</I>" );
			return;
			}
		id=(String)req.getTemplateParameter( 0 );

		qid= new Integer( id );
		QuestionnaireQuestion q=questionnaire.getQuestion( qid );
		if ( q==null )
			{
			out.println( "Unknown question ID." );
			return;
			}
		QuestionnaireResponse response;
		Vector responselist=new Vector();
		//java.util.Date d=new java.util.Date();

		Logger.getLogger("org.bodington").fine( "Questionnaire print paper A" );

		try
			{
			sql="SELECT * FROM " + DBObject.schema + "questionnaire_responses "+
				"WHERE (question_id = " + id + ") " +
				"ORDER BY item	";
			
			results=db.select( sql );
			if ( results==null )
				{
				out.println( "<HR>Problem fetching comments<HR>" );
				return;
				}
			
			while ( results.next() )
				{
				response=new QuestionnaireResponse();
				response.load( results );
				responselist.addElement( response );
				}
			//out.println( "</PRE>" );
			}
		catch ( Exception ex )
			{
			out.println( "<HR>Problem fetching comments<HR>" + ex );
			return;
			}

		Logger.getLogger("org.bodington").fine( "Questionnaire print paper B" );
		
		q.printComments( "/icons/", out, responselist );

		Logger.getLogger("org.bodington").fine( "Questionnaire print paper C" );
		*/
		}


	
	private void qrecord(  Request req, PrintWriter out, QuestionnaireSession q_session, String insertname )
		throws IOException, BuildingServerException
		{
		char letter;
		int i, j;
		String param;
		Vector questions_in_order;
		PrimaryKey[] list;
		QuestionnaireQuestion q;
		int items[];
		String comments[];
		User user = (User)BuildingContext.getContext().getUser();
		questions_in_order = q_session.getQuestionnaireQuestionsInOrder();
			
		items = new int[questions_in_order.size()];
		comments = new String[questions_in_order.size()];
		list = new PrimaryKey[questions_in_order.size()];
		
		for ( i=0; i<questions_in_order.size(); i++ )
			{
			q=(QuestionnaireQuestion)questions_in_order.elementAt( i );
			list[i] = q.getQuestionnaireQuestionId();
		
			//if no selection this is indicated with item = 100
			items[i]=100;
			comments[i]=null;
			
			// is the question present?
			param=req.getParameter( "Q" + list[i] );
			if ( param==null || !param.equalsIgnoreCase( "true" ) )
				continue;
				

			param=req.getParameter( "QR" + list[i] );
			if ( param!=null && param.length()>0 )
				{
				for ( j=0; j<10; j++ )
					{
					letter=(char)('A'+j);
					if ( param.charAt( 0 )==letter )
						{
						items[i]=j;
						break;
						}
					}
				}

			comments[i]=req.getParameter( "QC" + list[i] );
			if ( comments[i]!=null )
				comments[i]=comments[i].trim();
			
			}
			
			
		PrimaryKey result_id =  q_session.record( list, items, comments );
		
		out.println( "<P>Your response have been recorded .</P>" );
			
        Event event = new OpinionEvent( 
        				OpinionEvent.EVENT_RECORD,
        				req.getResource().getResourceId(), 
        				user.getUserId(), 
        				new Integer( result_id.intValue() ) );
        event.save();
		}



	private void qrunbutton(  Request req, PrintWriter out, QuestionnaireSession q_session )
		throws IOException
		{
		out.println( "<INPUT NAME=run TYPE=BUTTON ONCLICK=\"launchtest()\" VALUE=\"Show Questions Now\">" );
		
		return;
		}

	private void export(  Request req, PrintWriter out, QuestionnaireSession q_session )
		throws IOException
		{
		try
		    {
		    q_session.exportXml( true, true );
    		out.println( "<P>The XML file has been created and is available for <A HREF=qti.xml>download</A> now.</P>" );
    		out.println( "<P>(Left click to view in browser, right click to save to disk.) " );
		    }
		catch ( BuildingServerException bsex )
		    {
    		out.println( "<PRE>" );
    		out.println( bsex.getMessage() );
    		out.println( "</PRE>" );
		    }
		
		
		return;
		}

	private void importq(  Request req, PrintWriter out, QuestionnaireSession q_session )
		throws IOException
		{
		String file = req.getParameter( "file" );
		if ( file == null || file.length() == 0 )
		    {
		    out.println( "<P>Import failed: no file was supplied.</P>" );
		    return;
		    }

		try
		    {
		    q_session.importXmlQuestions( file );
    		out.println( "DONE" );
		    }
		catch ( BuildingServerException bsex )
		    {
    		out.println( "<PRE>" );
    		out.println( bsex.getMessage() );
    		out.println( "</PRE>" );
		    }
		
		
		return;
		}

	}


