Author: arkurth
Date: Thu Mar 19 18:27:06 2009
New Revision: 756127

URL: http://svn.apache.org/viewvc?rev=756127&view=rev
Log:
VCL-112
Added DataStructure.pm::retrieve_user_data(). This subroutine retrieves user 
data from the database. It adds flexibility in that the DataStructure class can 
be used to retrieve user data whether or not a reservation exists for that 
user. It will be used in the near future to retrieve the data about an image 
owner so that the image affiliation can be determined. Image owner detailed 
data is not being retrieved when a DataStructure object is created based on a 
reservation.

There are no hard-coded column names in the subroutine code. The column names 
are retrieved from the information_schema database.  

The subroutine can be called as either an object method or class function. A 
default value had to be added to request_data in order for this to work without 
warning messages. Arguments can either be a user ID or login ID. If no argument 
is given, the subroutine must be called as an object method and a user ID must 
already be stored in the DataStructure.

Modified:
    incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm

Modified: incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=756127&r1=756126&r2=756127&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm Thu Mar 19 
18:27:06 2009
@@ -491,7 +491,7 @@
 
 =cut
 
-my @request_data : Field : Arg('Name' => 'request_data') : Get('Name' => 
'request_data', 'Private' => 1) : Set('Name' => 'refresh_request_data', 
'Private' => 1);
+my @request_data : Field : Arg('Name' => 'request_data', 'Default' => {}) : 
Get('Name' => 'request_data', 'Private' => 1) : Set('Name' => 
'refresh_request_data', 'Private' => 1);
 
 =head3 @blockrequest_data
 
@@ -500,7 +500,7 @@
 
 =cut
 
-my @blockrequest_data : Field : Arg('Name' => 'blockrequest_data') : 
Get('Name' => 'blockrequest_data', 'Private' => 1);
+my @blockrequest_data : Field : Arg('Name' => 'blockrequest_data', 'Default' 
=> {}) : Get('Name' => 'blockrequest_data', 'Private' => 1);
 
 ##############################################################################
 
@@ -1082,8 +1082,173 @@
 
        notify($ERRORS{'OK'}, 0, "valid subroutines:\n$output");
 } ## end sub print_subroutines
+
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 retrieve_user_data
+
+ Parameters  : If subroutine is called as a DataStructure object method an no 
arguments are supplied:
+                  -the user ID stored in the DataStructure object is used
+                                               -the user login ID stored in 
the DataStructure object is used if the user ID is not set
+                                               -if neither the user ID or 
login ID are set in the object, an error message is generated and null is 
returned
+                                       If subroutine is NOT called as an 
object method, either of the following must be passed:
+                                          -user ID containing all digits 
(example: retrieve_user_data(2870))
+                                               -user ID containing all digits 
(example: retrieve_user_data('ibuser'))
+                                               -if an argument is not passed, 
an error message is generated and null is returned
+ Returns     : If successful: hash reference containing user data (evaluates 
to true)
+               If failed: undefined (evaluates to false)
+ Description : This subroutine attempts to retrieve data for a user.
+               If called as an object method the user data is stored in the 
DataStructure object.
+                                       If called as a class function, the data 
can be utilized by accessing the hash reference returned.
+                                       A populated DataStructure object does 
not need to be created in order to use this subroutine.
+                                       A reservation is not required in order 
to use this subroutine.
+                                       Examples:
+                                       use VCL::DataStructure;
+                                       
+                                       # Called as a class function
+                                       my $user_data = 
VCL::DataStructure::retrieve_user_data(2870);
+                                       foreach my $key (sort 
keys(%{$user_data})) {
+                                               print "key: $key, value: 
$user_data->{$key}\n";
+                                       }
+                                       
+                                       # Called as an object method
+                                       
$self->data->retrieve_user_data('ibuser');
+                                       print $self->data->get_user_id();
+
+=cut
+
+sub retrieve_user_data {
+       my $self;
+       my $argument = shift;
+       
+       # Check if subroutine was called as an object method
+       if (ref($argument) =~ /DataStructure/) {
+               # Subroutine was called as an object method, get next argument
+               $self = $argument;
+               $argument = shift;
+       }
+       
+       # Get a hash containing all of the tables and columns in the database
+       my $database_table_columns = VCL::utils::get_database_table_columns();
+       if (!$database_table_columns) {
+               notify($ERRORS{'WARNING'}, 0, "database table and column names 
could not be retrieved");
+               return;
+       }
+       
+       # Assemble a hash containing table names and aliases to be used in the 
select statement
+       my %tables_to_join = (
+               'user' => 'user',
+               'adminlevel' => 'user_adminlevel',
+               'affiliation' => 'user_affiliation',
+               'IMtype' => 'user_IMtype',
+       );
+       
+       # Assemble the WHERE part of the select statement
+       # The user must be specified by either passing an id or login_id 
argument
+       my $where_clause;
+       if ($argument && $argument =~ /^\d+$/) {
+               # Simple scalar argument was passed containing all digits, 
assume it's the user id
+               $where_clause = "user.id = '$argument'\n";
+       }
+       elsif ($argument) {
+               # Simple scalar argument was passed not consisting of all 
digits, assume it's the user login id
+               $where_clause = "user.unityid = '$argument'\n";
+       }
+       elsif ($self && (my $user_id = $self->get_user_id())) {
+               # Argument was not passed but subroutine was called as a 
DataStructure object method
+               # $self->get_user_id() returned something
+               $where_clause = "user.id = '$user_id'\n";
+       }
+       elsif ($self && (my $user_login_id = $self->get_user_login_id())) {
+               # Argument was not passed but subroutine was called as a 
DataStructure object method
+               # $self->get_user_login_id() returned something
+               $where_clause = "user.unityid = '$user_login_id'\n";
+       }
+       elsif (!$self) {
+               notify($ERRORS{'WARNING'}, 0, "unable to determine which user 
to query, subroutine was not called as an object method and id or login id 
argument was not passed");
+               return;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "unable to determine which user 
to query, subroutine was called as an object method but get_user_id() and 
get_user_login_id() did not return values");
+               return;
+       }
+       
+       notify($ERRORS{'DEBUG'}, 0, "attempting to retrieve and store data for 
user: $where_clause");
+       
+       # Add the tables to join to the WHERE clause
+       $where_clause .= "AND user.adminlevelid = user_adminlevel.id\n";
+       $where_clause .= "AND user.affiliationid = user_affiliation.id\n";
+       $where_clause .= "AND user.IMtypeid = user_IMtype.id\n";
+       
+       # Loop through the tables which will be joined together and assemble 
the columns part of the select statement
+       # Get the column names for each table
+       # Assemble a line for each column: tablealias_table.column AS 
tablealias_column
+       my $sql_query_columns;
+       foreach my $table_to_join (keys(%tables_to_join)) {
+               my $table_alias = $tables_to_join{$table_to_join};
+               for my $column (@{$database_table_columns->{$table_to_join}}) {
+                       $sql_query_columns .= "$table_alias.$column AS 
$table_alias\_$column,\n";
+               }
+               $sql_query_columns .= "\n";
+       }
+       
+       # Remove the last comma and trailing newlines from the column names 
string
+       $sql_query_columns =~ s/,\n+$//;
+       
+       # Use join to put together the FROM part of the select statement
+       # This generates a string:
+       #    table1 tablealias1,
+       #    table2 tablealias2...
+       my $from_clause = join(",\n", map ("$_ $tables_to_join{$_}", 
keys(%tables_to_join)));
+       
+       # Assemble the select statement
+       my $sql_select_statement = "SELECT 
DISTINCT\n\n$sql_query_columns\n\nFROM\n$from_clause\n\nWHERE\n$where_clause";
+       
+       # Call database_select() to execute the select statement and make sure 
1 row was returned
+       my @select_rows = VCL::utils::database_select($sql_select_statement);
+       if (!scalar @select_rows == 1) {
+               notify($ERRORS{'WARNING'}, 0, "select statement returned " . 
scalar @select_rows . " rows:\n" . join("\n", $sql_select_statement));
+               return;
+       }
+       
+       # $select_rows[0] is a hash reference, the keys are the column names
+       # Loop through the column names and add the data to $self->request_data
+       my $user_data_row = $select_rows[0];
+       my %user_data_hash;
+       foreach my $column_name (sort keys(%{$user_data_row})) {
+               # Get the data value for the column
+               my $user_data_value = $user_data_row->{$column_name};
+               
+               # The column name is in the format: user_affiliation_name
+               # Underscores represent hash depth
+               # Transform the column name: user_affiliation_name --> 
{user}{affiliation}{name}
+               (my $hash_path = "{$column_name}") =~ s/_/}{/g;
+               
+               # Use eval to set the correct data key to the value
+               eval '$user_data_hash' . $hash_path . '= $user_data_value';
+       }
+       
+       # Attempt to get the user ID and login ID from the data that was just 
retrieved
+       my $user_id = $user_data_hash{user}{id};
+       my $user_login_id = $user_data_hash{user}{unityid};
+       if (!$user_id && $user_login_id) {
+               notify($ERRORS{'WARNING'}, 0, "user id and login id could not 
be determined for user data just retrieved");
+               return;
+       }
+       
+       # If subroutine was called as an object method, replace the user key in 
the request data
+       if ($self) {
+               $self->request_data->{user} = $user_data_hash{user};
+               notify($ERRORS{'DEBUG'}, 0, "data has been stored for user: 
$user_login_id (id: $user_id)");
+       }
+       else {
+               notify($ERRORS{'DEBUG'}, 0, "data has been retrieved for user: 
$user_login_id (id: $user_id)");
+       }
+       
+       return $user_data_hash{user};
+}
+
+#/////////////////////////////////////////////////////////////////////////////
 
 1;
 __END__


Reply via email to