/* ======================================================================
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.server.realm;

import org.bodington.server.resources.*;
import org.bodington.server.realm.*;
import org.bodington.server.*;
import org.bodington.sqldatabase.*;
import org.bodington.database.*;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;


/**
 * Represents properties and code for editing sets of aliases.
 * 
 * @author Jon Maber
 * @version 1.0
 */
public class AliasEditor extends org.bodington.server.resources.Resource
	{

	// return a class that will 'front end' the resource
	// for a user.
	public Class sessionClass()
		{
		return UserManagementSessionImpl.class;
		}


    
	private void checkAliasParameters( PrimaryKey aliasid, String s, boolean is_primary, String user_cat )
		throws BuildingServerException
	    {
	    int i;
		Alias alias, oldalias=null;
	    StringBuffer where = new StringBuffer( 64 );
	    
	    if ( !this.checkPermission( Permission.EDIT ) )
			throw new BuildingServerException( "You don't have 'edit' level access to this resource." );

		if ( aliasid!=null )
			{
			oldalias = Alias.findAlias( aliasid );
			if ( oldalias==null )
				throw new BuildingServerException( "The specified alias wasn't found." );
			Zone edit_zone = getEffectiveZone();
			Zone alias_zone = oldalias.getZone();
			if ( !edit_zone.equals( alias_zone ) )
				throw new BuildingServerException( "The specified alias can't be edited because it belongs to a different administrative zone." );
			}

	    if ( s==null )
			throw new BuildingServerException( "No name was specified for the new unique identifier." );
	    
	    s=s.trim();
	    if ( s.length()>64 )
			throw new BuildingServerException( "The specified name is too long (>64 characters)." );
	    if ( s.length()<1 )
			throw new BuildingServerException( "The specified name is too short (<1 character)." );
	    
	    char c;
	    for ( i=0; i<s.length(); i++ )
			{
			c=s.charAt(i);
			if ( !Character.isLetterOrDigit( c ) &&   c != '_'  &&  c != '-' &&  c != '.')
				throw new BuildingServerException( "The specified name can only contain letters digits, '-',  '_' or '.'." );
			}
			
		if ( oldalias != null )
			{
			where.append( "alias_id <> " );
			where.append( aliasid.toString() );
			where.append( " AND " );
			}
		where.append( "zone_id = " );
		where.append( getEffectiveZoneId().toString() );
		where.append( " AND alias_name = '" );
		where.append( s );
		where.append( "'" );
		alias = Alias.findAlias( where.toString() );
		if ( alias!=null )
			throw new BuildingServerException( "Another unique identifier already exists with the name that was given - you can't have two the same." );

		if ( is_primary )
			{
		    if ( user_cat==null )
				throw new BuildingServerException( "A user category list must be specified for the new primary unique identifier." );
	    	user_cat=user_cat.trim();
	    	if ( user_cat.length()>64 )
				throw new BuildingServerException( "The specified user category list is too long (>64 characters)." );
	    	if ( user_cat.length()<1 )
				throw new BuildingServerException( "The specified user category list is too short (<1 character)." );
				
			StringTokenizer tok = new StringTokenizer( user_cat, "," );
			if ( tok.countTokens()<1 )
				throw new BuildingServerException( "The specified user category list contains no entries." );
				
			String t;
			while ( tok.hasMoreTokens() )
				{
				t = tok.nextToken();
		    	if ( t.length()<1 )
					throw new BuildingServerException( "The specified user category is too short (<1 character)." );
	    		for ( i=0; i<t.length(); i++ )
					{
					c=t.charAt(i);
					if ( !Character.isLetterOrDigit( c ) &&   c != '_'  &&  c != '-' &&  c != '.')
						throw new BuildingServerException( "The user category can only contain letters digits, '-',  '_' or '.'." );
					}
				}
			
			/*
			where.setLength( 0 );
			if ( oldalias != null )
				{
				where.append( "alias_id <> " );
				where.append( aliasid.toString() );
				where.append( " AND " );
				}
			where.append( "zone_id = " );
			where.append( getEffectiveZoneId().toString() );
			where.append( " AND user_category = '" );
			where.append( user_cat );
			where.append( "'" );
			alias = Alias.findAlias( where.toString() );
			if ( alias!=null )
				throw new BuildingServerException( "Another  unique identifier already exists with the user category that was given - you can't have two the same." );
			*/
			}


		}


	public void createAlias( String s, boolean is_primary, String user_cat )
		throws BuildingServerException
	    {
	    Alias alias;
	    
	    checkAliasParameters( null, s, is_primary, user_cat );

		alias = new Alias();
		alias.setZoneId( getEffectiveZoneId() );
		alias.setAliasName( s );
		alias.setAliasType( is_primary?new Integer( Alias.TYPE_PRIMARY ):new Integer( Alias.TYPE_SECONDARY ) );	
		alias.setUserCategory( is_primary?user_cat.trim():null );
		alias.save();
	    }
	    

	public void editAlias( PrimaryKey aliasid, String s, boolean is_primary, String user_cat )
		throws BuildingServerException
	    {
	    Alias alias;
	    checkAliasParameters( aliasid, s, is_primary, user_cat );
	    
		alias = Alias.findAlias( aliasid );
		if ( alias==null )
			throw new BuildingServerException( "The specified alias wasn't found." );
		alias.setZoneId( getEffectiveZoneId() );
		alias.setAliasName( s.trim() );
		alias.setAliasType( is_primary?new Integer( Alias.TYPE_PRIMARY ):new Integer( Alias.TYPE_SECONDARY ) );	
		alias.setUserCategory( is_primary?user_cat.trim():null );
		alias.save();
	    }
	    

	public void createAliasEntries( String alias_name, BufferedReader reader )
		throws BuildingServerException
	    {
	    Vector entry_list=new Vector();
		Alias alias;
	    
	    if ( !this.checkPermission( Permission.EDIT ) )
			throw new BuildingServerException( "You don't have 'edit' level access to this resource." );

	    String s=alias_name.trim();
		alias = Alias.findAlias( "zone_id = " + getEffectiveZoneId() + " AND alias_name = " + SqlDatabase.quotedSQL( alias_name ) );
		if ( alias==null )
			throw new BuildingServerException( "The specified unique identifier doesn't exist within the adminsitrative zone." );

		String line, value;
		AliasEntry entry;
		StringTokenizer tok;
		int id, i;
	    char c;
		try
			{
			line = reader.readLine();
			while ( line!=null )
				{
				tok=new StringTokenizer( line, "\t" );
				if ( tok.countTokens()==0 )
					continue;
				if ( tok.countTokens()!=2 )
					throw new BuildingServerException( "Invalid input - two columns delimited by TABS expected." );
				try
					{
					id = Integer.parseInt( tok.nextToken() );
					}
				catch ( NumberFormatException numex )
					{
					throw new BuildingServerException( "Invalid input - first column should contain bodington system ID numbers." );
					}

				value=tok.nextToken();
	    		for ( i=0; i<value.length(); i++ )
					{
					c=value.charAt(i);
					if ( !Character.isLetterOrDigit( c ) &&   c != '_'  &&  c != '-' &&  c != '.' )
						throw new BuildingServerException( "Values in column two can only contain letters digits, '-' or '_' or '.'." );
					}

				entry = new AliasEntry();
				entry.setAlias( alias );
				entry.setUserId( new PrimaryKey( id ) );
				entry.setUserAlias( value );
				//don't save entries until they are all parsed in without error
				entry_list.addElement( entry );
				
				line = reader.readLine();
				}
			}
		catch ( IOException ioex )
			{
			throw new BuildingServerException( "IO Error reading input.\n" + ioex );
			}
		
		for ( int j=0; j< entry_list.size(); j++ )
			{
			entry = (AliasEntry)entry_list.elementAt( j );
			entry.save();
			}
		
		return;
		}



	public Enumeration findEditableAliases()
		throws BuildingServerException
		{
		PrimaryKey zid = getEffectiveZoneId();
		if ( zid == null )
			throw new BuildingServerException( "This tool is not within a defined administrative zone." );
		return Alias.findAliases( "zone_id = " + zid.toString() );
		}

	public String getPrefix()
		throws BuildingServerException
		{
		StringBuffer name = new StringBuffer();
		boolean in_groups;
		Resource current;
		Enumeration ancestors = this.findAncestors();
		
		in_groups=false;
		while ( ancestors.hasMoreElements() )
			{
			current = (Resource)ancestors.nextElement();
			if ( in_groups )
				{
				if ( this.getHttpFacilityNo() != current.getHttpFacilityNo() )
					{
					in_groups=false;
					name.setLength( 0 );
					continue;
					}
				name.append( current.getName() );
				name.append( "." );
				}
			else
				{
				if ( this.getHttpFacilityNo() == current.getHttpFacilityNo() )
					{
					in_groups=true;
					name.setLength( 0 );
					name.append( current.getName() );
					name.append( "." );
					}
				}
			}

		if ( name.length() == 0 )
			return null;
			
		return name.toString();
		}

	}

