package mit.roles ;

public class Function
implements roles.Function
{
	private final static String FUNCTION_ID = "FUNCTION_ID" ;
	private final static String FUNCTION_NAME = "FUNCTION_NAME" ;
	private final static String FUNCTION_DESCRIPTION = "FUNCTION_DESCRIPTION" ;
	private final static String FUNCTION_CATEGORY = "FUNCTION_CATEGORY" ;
	private final static String QUALIFIER_TYPE = "QUALFIER_TYPE" ;
	private final static String PRIMARY_AUTHORIZABLE = "PRIMARY_AUTHORIZABLE" ;
	private final static String MODIFIED_BY = "MODIFIED_BY" ;
	private final static String MODIFIED_DATE = "MODIFIED_DATE" ;

	private mit.roles.RolesFactory rolesFactory = null ;
	public mit.roles.RolesFactory getRolesFactory() { return rolesFactory ; }
	protected void setRolesFactory( mit.roles.RolesFactory rolesFactory )
		{ this.rolesFactory = rolesFactory ; }

	private java.util.Properties properties = null ;
	public java.util.Properties getProperties() { return this.properties ; }
	private void setProperties( java.util.Properties properties )
		{ this.properties = properties ; }

	public Object getId()
	{
		if( null != this.properties )
		{
			return this.properties.get( FUNCTION_ID ) ;
		}
		return null ;
	}
	public void setId( Object id )
	{
		if( null == this.properties )
		{
			this.properties = new java.util.Properties() ;
		}
		this.properties.put( FUNCTION_ID , id ) ;
	}

	public String getName()
	{
		if( null != this.properties )
		{
			return ( String ) this.properties.get( FUNCTION_NAME ) ;
		}
		return null ;
	}
	public void setName( String name )
	{
		if( null == this.properties )
		{
			this.properties = new java.util.Properties() ;
		}
		this.properties.put( FUNCTION_NAME , name ) ;
	}

	public String getDescription()
	{
		if( null != this.properties )
		{
			return ( String ) this.properties.get( FUNCTION_DESCRIPTION ) ;
		}
		return null ;
	}
	protected void setDescription( String description )
	{
		if( null == this.properties )
		{
			this.properties = new java.util.Properties() ;
		}
		this.properties.put( FUNCTION_DESCRIPTION , description ) ;
	}

	public roles.FunctionCategory getFunctionCategory()
	{
		if( null != this.properties )
		{
			return ( roles.FunctionCategory ) this.properties.get( FUNCTION_CATEGORY ) ;
		}
		return null ;
	}
	public void setFunctionCategory( roles.FunctionCategory functionCategory )
	{
		if( null == this.properties )
		{
			this.properties = new java.util.Properties() ;
		}
		this.properties.put( FUNCTION_CATEGORY , functionCategory ) ;
	}

	public roles.QualifierType  getQualifierType()
	{
		if( null != this.properties )
		{
			return ( roles.QualifierType ) this.properties.get( QUALIFIER_TYPE ) ;
		}
		return null ;
	}
	public void setQualifierType( roles.QualifierType  qualifierType )
	{
		if( null == this.properties )
		{
			this.properties = new java.util.Properties() ;
		}
		this.properties.put( QUALIFIER_TYPE , qualifierType ) ;
	}

	// Y(es) N(o) D(eptartment)
	public String getPrimaryAuthorizable()
	{
		if( null != this.properties )
		{
			return ( String ) this.properties.get( PRIMARY_AUTHORIZABLE ) ;
		}
		return null ;
	}
	protected void setPrimaryAuthorizable( String primaryAuthorizable )
	{
		if( null == this.properties )
		{
			this.properties = new java.util.Properties() ;
		}
		this.properties.put( PRIMARY_AUTHORIZABLE , primaryAuthorizable ) ;
	}

	public String getModifiedBy()
	{
		if( null != this.properties )
		{
			return ( String ) this.properties.get( MODIFIED_BY ) ;
		}
		return null ;
	}
	protected void setModifiedBy( String modifiedBy )
	{
		if( null == this.properties )
		{
			this.properties = new java.util.Properties() ;
		}
		this.properties.put( MODIFIED_BY , modifiedBy ) ;
	}

	public java.sql.Timestamp getModifiedDate()
	{
		if( null != this.properties )
		{
			return ( java.sql.Timestamp ) this.properties.get( MODIFIED_DATE ) ;
		}
		return null ;
	}
	protected void setModifiedDate( java.sql.Timestamp modifiedDate )
	{
		if( null == this.properties )
		{
			this.properties = new java.util.Properties() ;
		}
		this.properties.put( MODIFIED_DATE , modifiedDate ) ;
	}

	private Boolean foundInRoles = new Boolean( false ) ;
	public Boolean isFoundInRoles()
		throws Exception
	{
		if( ! this.foundInRoles.booleanValue() )
		{
			this.foundInRoles
				= new Boolean( isIdInRoles() || isNameAndCategoryInRoles() ) ;
		}
		return this.foundInRoles ;
	}

	public void refresh()
		throws Exception
	{
		if( ! isIdInRoles() )
		{
			isNameAndCategoryInRoles() ;
		}
	}

	public Function
		( mit.roles.RolesFactory rolesFactory
		, java.util.Properties properties
		)
	{
		setRolesFactory( rolesFactory ) ;
		setProperties( properties ) ;
	}

	public Function
		( mit.roles.RolesFactory rolesFactory
		, String name
		, String description
		, roles.FunctionCategory functionCategory
		, roles.QualifierType qualifierType
		)
	{
		setRolesFactory( rolesFactory ) ;
		setName( name ) ;
		setDescription( description ) ;
		setFunctionCategory( functionCategory ) ;
		setQualifierType( qualifierType ) ;
	}

	public Function
		( mit.roles.RolesFactory rolesFactory
		, Object id
		, String name
		, String description
		, roles.FunctionCategory functionCategory
		, roles.QualifierType qualifierType
		)
	{
		setRolesFactory( rolesFactory ) ;
		setId( id ) ;
		setName( name ) ;
		setDescription( description ) ;
		setFunctionCategory( functionCategory ) ;
		setQualifierType( qualifierType ) ;
	}

	protected Function
		( mit.roles.RolesFactory rolesFactory
		, Object id
		, String name
		, String description
		, roles.FunctionCategory functionCategory
		, roles.QualifierType qualifierType
		, String primaryAuthorizable
		, String modifiedBy
		, java.sql.Timestamp modifiedDate
		)
	{
		setRolesFactory( rolesFactory ) ;
		setId( id ) ;
		setName( name ) ;
		setDescription( description ) ;
		setFunctionCategory( functionCategory ) ;
		setQualifierType( qualifierType ) ;
		setPrimaryAuthorizable( primaryAuthorizable ) ;
		setModifiedBy( modifiedBy ) ;
		setModifiedDate( modifiedDate ) ;
	}

	public void delete()
		throws Exception
	{
		try
		{
			if( ( null != getRolesFactory() )
			&&  ( null != getRolesFactory().getConnection() )
			&&  ( null != getFunctionCategory() )
			&&  ( null != getQualifierType() )
			)
			{
				sql.Connection connection = getRolesFactory().getConnection() ;
				Object[] args = new Object[ 3 ] ;
				args[ 0 ] = getName() ;
				args[ 1 ] = getFunctionCategory().getCategory() ;
				args[ 2 ]
					= (
						( null != getRolesFactory().getForUser() )
						? ( ( mit.roles.Person ) getRolesFactory().getForUser() ).getKerberosName()
						: null
					) ;
				int[] columnTypes = new int[ 3 ] ;
				columnTypes[ 0 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 1 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 2 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				int[] dataTypes = new int[ 3 ] ;
				dataTypes[ 0 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 1 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 2 ] = java.sql.Types.VARCHAR ;
				connection.callProcedure
					( "ROLESAPI_DELETE_FUNCTION"
					, args
					, columnTypes
					, dataTypes
					) ;
				setRolesFactory( null ) ;
				setId( null ) ;
				setName( null ) ;
				setDescription( null ) ;
				setFunctionCategory( null ) ;
				setQualifierType( null ) ;
				setModifiedBy( null ) ;
				setModifiedDate( null ) ;
				return ;
			}
		}
		catch( Exception ex )
		{
			throw new roles.RolesException( ex.getMessage() ) ;
		}
		throw new roles.RolesException
			( roles.RolesException.INVALIDFUNCTION ) ;
	}

	public void update
		( String newName
		, String newDescription
		, roles.FunctionCategory newFunctionCategory
		, roles.QualifierType newQualifierType
		)
		throws Exception
	{
		try
		{
			if( ( null != getRolesFactory() )
			&&  ( null != getRolesFactory().getConnection() )
			&&  ( null != getId() )
			)
			{
				sql.Connection connection = getRolesFactory().getConnection() ;
				Object[] args = new Object[ 7 ] ;
				args[ 0 ] = this.getName() ;
				args[ 1 ] = this.getFunctionCategory().getCategory() ;
				args[ 2 ] =
					( null != newName )
					? newName
					: this.getName() ;
				args[ 3 ] =
					( null != newDescription )
					? newDescription
					: this.getDescription() ;
				args[ 4 ] =
					( null != newFunctionCategory )
					? newFunctionCategory.getCategory()
					: (
						( null != this.getFunctionCategory() )
						? this.getFunctionCategory().getCategory()
						: null
					  ) ;
				args[ 5 ] =
					( null != newQualifierType )
					? newQualifierType.getType()
					: (
						( null != this.getQualifierType() )
						? this.getQualifierType().getType()
						: null
					  ) ;
				args[ 6 ]
					= (
						( null != getRolesFactory().getForUser() )
						? ( ( mit.roles.Person ) getRolesFactory().getForUser() ).getKerberosName()
						: null
					  ) ;
				int[] columnTypes = new int[ 9 ] ;
				columnTypes[ 0 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 1 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 2 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 3 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 4 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 5 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 6 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 7 ] = java.sql.DatabaseMetaData.procedureColumnOut ;
				columnTypes[ 8 ] = java.sql.DatabaseMetaData.procedureColumnOut ;
				int[] dataTypes = new int[ 9 ] ;
				dataTypes[ 0 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 1 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 2 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 3 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 4 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 5 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 6 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 7 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 8 ] = java.sql.Types.VARCHAR ;
				sql.Table table =
					connection.callProcedure
						( "ROLESAPI_UPDATE_FUNCTION"
						, args
						, columnTypes
						, dataTypes
						) ;
				if( null != table )
				{
					setName( ( String ) args[ 2 ] ) ;
					setDescription( ( String ) args[ 3 ] ) ;
					mit.roles.FunctionCategory functionCategory
						= new mit.roles.FunctionCategory
							( ( String ) args[ 4 ]
							, null
							) ;
					setFunctionCategory( functionCategory ) ;
					mit.roles.QualifierType qualifierType
						= new mit.roles.QualifierType
							( getRolesFactory()
							, ( String ) args[ 5 ]
							, null
							) ;
					setQualifierType( qualifierType ) ;
					sql.Rows rows = table.getRows() ;
					if( rows.hasMoreRows() )
					{
						Object[] row = rows.nextRow() ;
						setModifiedBy ( ( String ) row[ 0 ] ) ;
						setModifiedDate( getRolesFactory().createSqlTimestamp
							( ( String ) row[ 1 ] ) ) ;
					}
					return ;
				}
			}
		}
		catch( Exception ex )
		{
			throw new roles.RolesException( ex.getMessage() ) ;
		}
		throw new roles.RolesException
			( roles.RolesException.INVALIDFUNCTION ) ;
	}

	public static roles.Function create
		( mit.roles.RolesFactory rolesFactory
		, String name
		, String description
		, roles.FunctionCategory functionCategory
		, roles.QualifierType qualifierType
		)
		throws Exception
	{
		try
		{
			if( ( null != rolesFactory )
			&&  ( null != rolesFactory.getConnection() )
			&&  ( null != name )
			&&  ( null != description )
			&&  ( null != functionCategory )
			&&  ( null != qualifierType )
			)
			{
				sql.Connection connection = rolesFactory.getConnection() ;
				Object[] args = new Object[ 5 ] ;
				args[ 0 ] = name ;
				args[ 1 ] = description ;
				args[ 2 ] = functionCategory.getCategory() ;
				args[ 3 ] = qualifierType.getType() ;
				args[ 4 ]
					= (
						( null != rolesFactory.getForUser() )
						? ( ( mit.roles.Person ) rolesFactory.getForUser() ).getKerberosName()
						: null
					) ;
				int[] columnTypes = new int[ 8 ] ;
				columnTypes[ 0 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 1 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 2 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 3 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 4 ] = java.sql.DatabaseMetaData.procedureColumnIn ;
				columnTypes[ 5 ] = java.sql.DatabaseMetaData.procedureColumnOut ;
				columnTypes[ 6 ] = java.sql.DatabaseMetaData.procedureColumnOut ;
				columnTypes[ 7 ] = java.sql.DatabaseMetaData.procedureColumnOut ;
				int[] dataTypes = new int[ 8 ] ;
				dataTypes[ 0 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 1 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 2 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 3 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 4 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 5 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 6 ] = java.sql.Types.VARCHAR ;
				dataTypes[ 7 ] = java.sql.Types.VARCHAR ;
				sql.Table table
					= connection.callProcedure
						( "ROLESAPI_CREATE_FUNCTION"
						, args
						, columnTypes
						, dataTypes
						) ;
				if( null != table )
				{
					sql.Rows rows = table.getRows() ;
					if( rows.hasMoreRows() )
					{
						Object row = rows.nextRow() ;
						java.util.Properties properties = new java.util.Properties() ;
						properties.put( rows.getColumnNames() , row ) ;
						return new mit.roles.Function
							( rolesFactory
							, properties
							) ;
					}
				}
			}
		}
		catch( Exception ex )
		{
			throw new roles.RolesException( ex.getMessage() ) ;
		}
		throw new roles.RolesException
			( roles.RolesException.INVALIDFUNCTION ) ;
	}

	public static roles.Function getFunction
		( mit.roles.RolesFactory rolesFactory
		, String functionName
		, roles.FunctionCategory functionCategory
		)
		throws Exception
	{
		try
		{
			if
				(  ( null != rolesFactory )
				&& ( null != rolesFactory.getConnection() )
				)
			{
				sql.Connection connection = rolesFactory.getConnection() ;
				sql.Table table = connection.executeQuery
					( getFunctionSQL
						( functionName , functionCategory.getCategory() )
					) ;
				if( null != table )
				{

					sql.Rows rows = table.getRows() ;
					if( rows.hasMoreRows() )
					{
						java.util.Properties properties = new java.util.Properties() ;
						properties.put( rows.getColumnNames() , rows.nextRow() ) ;
						return new mit.roles.Function
							( rolesFactory
							, properties
							) ;
					}
				}
				else
				{
					if( ! functionCategory.isFoundInRoles().booleanValue() )
					{
						throw new roles.RolesException
							( roles.RolesException.FUNCTIONCATEGORYNOTFOUNDINROLES ) ;
					}
				}
			}
		}
		catch( Exception ex )
		{
			throw new roles.RolesException( ex.getMessage() ) ;
		}
		throw new roles.RolesException
			( roles.RolesException.INVALIDFUNCTION ) ;
	}

	private static String getFunctionSQL
		( String functionName
		, String functionCategory
		)
	{
		String sql = "select" ;
		sql += "\n function_id, function_name, function_description, function_category, " ;
		sql += "\n modified_by, modified_date, qualifier_type" ;
		sql += "\n from function" ;
		sql += "\n where function_name = " + functionName ;
		sql += "\n and function_category = " + functionCategory + " ;" ;
		return sql ;
	}

	private boolean isIdInRoles()
		throws Exception
	{
		if( ( null != getId() )
		&&  ( null != getRolesFactory() )
		&&  ( null != getRolesFactory().getConnection() )
		)
		{
			sql.Connection connection = getRolesFactory().getConnection() ;
			sql.Table table
				= connection.executeQuery
					( new String
						( "select function_name, function_description, "
						+ "function_category, qualifier_type, "
						+ "primary_authorizable, modified_by, "
						+ "modified_date "
						+ "from function "
						+ "where function_id = "
						+ getId()
						+ " ;"
						)
					) ;
			if( null != table )
			{
				sql.Rows rows = table.getRows() ;
				if( rows.hasMoreRows() )
				{
					Object row = rows.nextRow() ;
					java.util.Properties properties = new java.util.Properties() ;
					properties.put( rows.getColumnNames() , row ) ;
					setProperties( properties ) ;
					return true ;
				}
			}
		}
		return false ;
	}

	private boolean isNameAndCategoryInRoles()
		throws Exception
	{
		if( ( null != getName() )
		&&  ( null != getFunctionCategory() )
		&&  ( null != getFunctionCategory().getCategory() )
		&&  ( null != getRolesFactory() )
		&&  ( null != getRolesFactory().getConnection() )
		)
		{
			sql.Connection connection = getRolesFactory().getConnection() ;
			sql.Table table
				= connection.executeQuery
					( new String
						( "select function_name, function_description, "
						+ "function_category, qualifier_type, "
						+ "primary_authorizable, modified_by, "
						+ "modified_date "
						+ "from function "
						+ "where function_name = "
						+ getName()
						+ " and function_category = "
						+ getFunctionCategory().getCategory()
						+ " ;"
						)
					) ;
			if( null != table )
			{
				sql.Rows rows = table.getRows() ;
				if( rows.hasMoreRows() )
				{
					Object row = rows.nextRow() ;
					java.util.Properties properties = new java.util.Properties() ;
					properties.put( rows.getColumnNames() , row ) ;
					setProperties( properties ) ;
					return true ;
				}
			}
		}
		return false ;
	}

}
