Webman-framework

Lightweight, Component-based, and Database-oriented Web Application Framework

About | Overview | Documentation

 

Documentation > Modules and APIs > webman_text2db_map

webman_text2db_map

 

Description:

Component-type module that provides database item operations mapping (insert/update/delete ) from simple text-formatted file content upload.

 

Dependencies:

Webman-framework's Core Modules:

  • HTML_DB_Map (Composition)
  • Text_DB_Map (Composition)
  • TLD_HTML_Map (Composition)

Webman-framework's Component-type Modules:
  • CGI_Component::webman_CGI_component (Inheritance)
  • webman_link_path_generator (Composition)

 

1. View Template

There are two view template files must be assigned to a single webman_text2db_map module. First is an upload form page to upload the text-formatted file and the second is a confirmation page for displaying database item field values extracted from the uploaded text-formatted file before proceed with insert/update/delete operations.

1.1 Upload Form Page

The DYNAMIC_CONTENT template-element (line 4) named link_path will be processed by webman_link_path_generator module inside process_DYNAMIC hook function. It's used as a place-holder to render current application's link path when webman_text2db_map module is called. The next DYNAMIC_CONTENT template-element (line 7) named form_hidden_field is used as place-holder for HTML-form's hidden input-element. This hidden input-element is used as an entity to pass the parameter named link_id (via POST-method) which is the standard CGI parameter name used to refer nodes' IDs that construct the overall application's link structure. The logic is to use again node's link-id which is used to call webman_text2db_map module previously.

File input-element named text_file_name (line 12) provides control for users to browse and select text file to be uploaded. Two form's submit buttons (lines 19-20) with identical name button_submit but having two different values (Upload and Cancel) are the default settings to provide users the options to proceed or cancel file upload submission. In other word the module by default will check the input type element named button_submit and look at its value either Upload or Cancel before decide to continue or cancel file upload form submission.

The last DYNAMIC_CONTENT template-element (line 31) named txt2db_format is used as a place-holder to display the structure of text-formatted file content should be used to match with the current database item rows and field columns format setting apllied to the module.

  1 <html>                                                                            
  2 <body>                                                                            
  3 <!-- start_view_ //-->                                                            
  4 <!-- dynamic_content_ name=link_path //--> &gt; Text to DB Operations             
  5 <p />                                                                             
  6 <form method="POST" action="./index.cgi" enctype="multipart/form-data">           
  7 <!-- dynamic_content_ name=form_hidden_field //-->                                
  8 <table border="1">                                                                
  9   <tr>                                                                            
 10     <td>Text File:</td>                                                           
 11     <td>                                                                          
 12       <input name="text_file_name" type="file" id="text_file_name">               
 13     </td>                                                                         
 14   </tr>                                                                           
 15                                                                                   
 16   <tr>                                                                            
 17     <td>&nbsp;</td>                                                               
 18     <td>                                                                          
 19       <input name="button_submit" type="submit" id="button_submit" value="Upload">
 20       <input name="button_submit" type="submit" id="button_submit" value="Cancel">
 21    </td>                                                                          
 22   </tr>                                                                           
 23 </table>                                                                          
 24 </form>                                                                           
 25                                                                                   
 26 <table border="1">                                                                
 27   <tr><th>Input Text File Format</th></tr>                                        
 28                                                                                   
 29   <tr>                                                                            
 30     <td>                                                                          
 31     <!-- dynamic_content_ name=txt2db_format //-->                                
 32     </td>                                                                         
 33   </tr>                                                                           
 34 </table>                                                                          
 35                                                                                   
 36 <!-- end_view_ //-->                                                              
 37 </body>                                                                           
 38 </html>                                                                           

1.2 Confirmation Form Page

At application runtime toward confirmation phase (file upload execution), data items extracted from text-formatted file content are reconstructed as Table_List_Data instance. Item field names and values from the constructed Table_List_Data instance are later accessed and stored as database cached CGI parameters. These database cached CGI parameters are the exact one that will be used in the database operation currently apllied to the module. At the same time, data items from Table_List_Data instance can be displayed prior the real database operation for confirmation purpose. There are an options of view templates to be used to render these data items by either simply use module's built-in item listing view logic or arrange the list view presentation using LIST template-element that will later be manipulated by TLD_HTML_Map core module.

1.2.1 Simple Item List

The DYNAMIC_CONTENT template-elements (lines 4 and 7) have the same roles as DYNAMIC_CONTENT template-elements used in upload form page (sub section 1.1, code lines 4 and 7). The next DYNAMIC_CONTENT template-element (line 9) named txt2db_item is a place-holder to display the rows of extracted item fields and values from text-formatted file content using module's built-in item listing view logic.

Two form's submit buttons (lines 11-12) with identical name button_submit but having two different values (Confirm and Cancel) are the default settings to provide users the options to proceed or cancel database operation mapping currently applied to the module.

  1 <html>                                                                         
  2 <body>                                                                         
  3 <!-- start_view_ //-->                                                         
  4 <!-- dynamic_content_ name=link_path //--> &gt; Text to DB Operations          
  5 <p />                                                                          
  6 <form method="POST" action="./index.cgi">                                      
  7 <!-- dynamic_content_ name=form_hidden_field //-->                             
  8 <div align="center">                                                           
  9   <!-- dynamic_content_ name=txt2db_item //-->                                 
 10   <br />                                                                       
 11   <input name="button_submit" type="submit" id="button_submit" value="Confirm">
 12   <input name="button_submit" type="submit" id="button_submit" value="Cancel"> 
 13 </div>                                                                         
 14 </form>                                                                        
 15 <!-- end_view_ //-->                                                           
 16 </body>                                                                        
 17 </html>                                                                        

1.2.2 LIST template-element Item List

The DYNAMIC_CONTENT template-elements (lines 4 and 7) have the same roles as DYNAMIC_CONTENT template-elements used in upload form page (sub section 1.1, code lines 4 and 7). Two form's submit buttons (lines 27-28), play the same roles such as explained previously (sub section 1.2.1 , code lines 11-12).

Inside the webman_text2db_map module, item list structure from text-formatted file content is extracted and then reconstructed as Table_List_Data instance by Text_DB_Map core module. The LIST template-element named txt2db_item (lines 19-24) will be passed to process_LIST hook function and then manipulated by TLD_HTML_Map module, the core module that responsible to map items from the previously mentioned Table_List_Data instance into LIST template-element content structure.

  1 <html>                                                                         
  2 <body>                                                                         
  3 <!-- start_view_ //-->                                                         
  4 <!-- dynamic_content_ name=link_path //--> &gt; Text to DB Operations          
  5 <p />                                                                          
  6 <form method="POST" action="./index.cgi">                                      
  7 <!-- dynamic_content_ name=form_hidden_field //-->                             
  8 <div align="center">                                                           
  9                                                                                
 10   <table border="1">                                                           
 11     <tr style="font-size:13px;">                                               
 12       <th>Num.</th>                                                            
 13       <th>field_caption_1_</th>                                                
 14       <th>field_caption_2_</th>                                                
 15       <th>field_caption_n_</th>                                                
 16     </tr>                                                                      
 17                                                                                
 18     <!-- start_list_ name=txt2db_item //-->                                    
 19     <tr>                                                                       
 20       <td align="right">$tld_num_.</td>                                        
 21       <th>$tld_field_name_1_</th>                                              
 22       <th>$tld_field_name_2_</th>                                              
 23       <th>$tld_field_name_n_</th>                                              
 24     </tr>                                                                      
 25     <!-- end_list_ //-->                                                       
 26   </table>                                                                     
 27                                                                                
 28   <br />                                                                       
 29   <input name="button_submit" type="submit" id="button_submit" value="Confirm">
 30   <input name="button_submit" type="submit" id="button_submit" value="Cancel"> 
 31 </div>                                                                         
 32 </form>                                                                        
 33 <!-- end_view_ //-->                                                           
 34 </body>                                                                        
 35 </html>                                                                        


 
2. Instantiation and Basic Parameter Setting

Generally below are the most basic parameter settings specific to module's main task to map database operations from text-formatted file content.

  • Database operation mapping to be applied (line 11).
  • Optionally change the default item rows and columns spliter (lines 15 and 18).
  • Database table name and field names involved in the database operation applied to the module (lines 23-24).
  • Key-field names mainly used for item update/delete operations and to detect duplicate entry in the insert operation (line 35).
More detailed explanations for these basic parameter settings are given as a comments before each color-marked function calls below.
  1 $component = new webman_text2db_map;                                                                          
  2                                                                                                               
  3 $component->set_CGI($cgi);                                                                                    
  4 $component->set_DBI_Conn($db_conn);                                                                           
  5                                                                                                               
  6 ### If not set,the default can be insert/update/delete depend                                                 
  7 ### on the combination of field list and key field name. Read                                                 
  8 ### in set_Key_Field_Name section for more explanation. However,                                              
  9 ### for the sake of clarity, it's advisable for developers to                                                 
 10 ### confirm the task by using set_Task function below.                                                        
 11 $component->set_Task($task);                                                                                  
 12                                                                                                               
 13 ### Default column spliter for text-formatted file content is "\t".                                           
 14 ### Other characters such as "|", ":", and "," are also possible.                                             
 15 #$component->set_Spliter_Column($spliter_col);                                                                
 16                                                                                                               
 17 ### Default row spliter for text file content is "\n".                                                        
 18 #$component->set_Spliter_Row($spliter_row);                                                                   
 19                                                                                                               
 20 ### Set table name and its field names involved in text-formatted                                             
 21 ### content to database operations mapping. The field names are                                               
 22 ### actually only relevant for insert/update operations.                                                      
 23 $component->set_Table_Name($table_name);                                                                      
 24 $component->set_Field_List("field_name_1_ ... field_name_n_");                                                
 25                                                                                                               
 26 ### If one of the key-field is also one of the field list set via set_Field_List function and the type of     
 27 ### database operation has been left unset, the operation by default switched to update instead of insert.    
 28 ### For the same scenario but there is only one field list, the operation will be set to delete. To           
 29 ### overwrite this default mechanism, just set the task manually via set_Task function. Other than used as    
 30 ### a keys to define the operation types, the key-field names in their more useful nature are used as a       
 31 ### keys for item update/delete operations, and specifically used to detect/avoid duplicate entry in insert   
 32 ### operation. The key-field names are passed as a single string argument split by space characters that will 
 33 ### construct key-field names constraint using "or" conditions. For "and" condition just mix the key-field    
 34 ### names such as follows: "key_field_name_2_&key_field_name_3_"                                              
 35 $component->set_Key_Field_Name("key_field_name_1_ key_field_name_2_&key_field_name_3_ ... key_field_name_n_");
 36                                                                                                               
 37 ### Add key-field from the current available CGI parameters and values. The                                   
 38 ### key-field string final result will be added into the key-field string                                     
 39 ### constructed by the pervious $component->set_Key_Field_Name(...)                                           
 40 ### function call.                                                                                            
 41 $component->set_Key_Field_Name_Dynamic("key_field_name_1_='$cgi_key_field_name_1__' and ... );                
 42                                                                                                               
 43 ### Option to debug SQL satement generated by the module.                                                     
 44 $component->set_SQL_Debug(1);                                                                                 
 45                                                                                                               
 46 #$component->set_Submit_Button_Name($submit_button_name);  ### default is "button_submit"                     
 47 #$component->set_Proceed_On_Submit($proceed_button_value); ### default is "Upload"                            
 48 #$component->set_Confirm_On_Submit($confirm_button_value); ### default is "Confirm"                           
 49 #$component->set_Cancel_On_Submit($cancel_button_value);   ### default is "Cancel"                            
 50                                                                                                               
 51 $component->set_Template_Default($template_file);                                                             
 52 $component->set_Template_Default_Confirm($template_file_confirm);                                             
 53                                                                                                               


 
3. Component-type Generic Function Calls

The proposed implementations below are slightly different from the basic generic function calls of standard component-type modules since webman_text2db_map is categorized as multi phases component-type module. The main differences are:

  • Component's run_Task function (line 50) will return the status of true or false. It's true if the update operation is proceed and succeed. Other extra tasks for handling this status condition is now considerable (lines 52-55).
  • There are requirements to do other related tasks if update operation has reach its last phase (lines 63-70).
When last phase has been reached there are options to change the current active page by directly change the content (line 66) or just redirect the page to other URL (line 69). However, within the context of framework's sub-controller implementation using webman_component_selector module, these last phase tasks options is not really necessary since the module will automatically reset some related CGI parameters when last phase has been reached causing the sub-controller running other correspond module for its next recursive module's function call.
 48 if ($component->authenticate) {                                   
 49     ### $status == 1 if update operation is proceed and succeed.  
 50     my $status = $component->run_Task;                            
 51                                                                   
 52     if ($status) {                                                
 53         ### Do other extra tasks if database operation is succeed.
 54         ### ...                                                   
 55     }                                                             
 56                                                                   
 57     $component->process_Content;                                  
 58 }                                                                 
 59                                                                   
 60 my $content = undef;                                              
 61                                                                   
 62 if ($component->last_Phase) {                                     
 63     $component->end_Task;                                         
 64                                                                   
 65     ### Set to other related content .                            
 66     #$content = "...";                                            
 67                                                                   
 68     ### Jump to other URL.                                        
 69     #$cgi->redirect_Page($url);                                   
 70                                                                   
 71 } else {                                                          
 72     $content = $component->get_Content;                           
 73 }                                                                 


 
4. Child Module for Customization

Most generic customization tasks are reflect to multi-phases character featured by the base module as already explained in the previous section (section 3). Customizations inside child modules provide more fine-grained control on each phases involved (lines 43-50). An equivalent tasks from previous example (section 3) for handling succeed current mapped database operations can be done internally inside the child module (lines 54-56 and lines 80-84).

Other customization tasks that are more specific to module's main business are done by overriding module's functions customize_TLD_DB_Operation (lines 99-107) and customize_TLD_View (lines 125-133). It provides options to manipulate Table_List_Data instance generated from text-formatted file content either the real database operations or just for information display only.

  1 package child_module_name;                               
  2                                                                            
  3 use webman_text2db_map;                                                    
  4                                                                            
  5 @ISA=("webman_text2db_map");                                               
  6                                                                            
  7 sub new {                                                                  
  8     my $class = shift;                                                     
  9                                                                            
 10     my $this = $class->SUPER::new();                                       
 11                                                                            
 12     #$this->set_Debug_Mode(1, 1);                                          
 13                                                                            
 14     bless $this, $class;                                                   
 15                                                                            
 16     return $this;                                                          
 17 }                                                                          
 18                                                                            
 19 sub get_Name {                                                             
 20     my $this = shift @_;                                                   
 21                                                                            
 22     return __PACKAGE__;                                                    
 23 }                                                                          
 24                                                                            
 25 sub get_Name_Full {                                                        
 26     my $this = shift @_;                                                   
 27                                                                            
 28     return $this->SUPER::get_Name_Full . "::" . __PACKAGE__;               
 29 }                                                                          
 30                                                                            
 31 sub run_Task {                                                             
 32     my $this = shift @_;                                                   
 33                                                                            
 34     my $cgi = $this->get_CGI;                                              
 35     my $dbu = $this->get_DBU;                                              
 36     my $db_conn = $this->get_DB_Conn;                                      
 37                                                                            
 38     my $login_name = $this->get_User_Login;                                
 39     my @groups = $this->get_User_Groups;                                   
 40                                                                            
 41     my $match_group = $this->match_Group($group_name_, @groups);           
 42                                                                            
 43     if ($this->init_Phase) {                                               
 44         ### init. phase extra tasks                                        
 45         #$cgi->add_Debug_Text("init_Phase", __FILE__, __LINE__, "TRACING");
 46                                                                            
 47     } elsif($this->last_Phase) {                                           
 48         ### last phase extra tasks                                         
 49         #$cgi->add_Debug_Text("last_Phase", __FILE__, __LINE__, "TRACING");
 50     }                                                                      
 51                                                                            
 52     my $status = $this->SUPER::run_Task();                                 
 53                                                                            
 54     if ($status) {                                                         
 55         ### extra tasks after update operation is succeed                  
 56     }                                                                      
 57 }                                                                          
 58                                                                            
 59 sub end_Task {                                                             
 60     my $this = shift @_;                                                   
 61                                                                            
 62     my $cgi = $this->get_CGI;                                              
 63     my $dbu = $this->get_DBU;                                              
 64     my $db_conn = $this->get_DB_Conn;                                      
 65                                                                            
 66     my $login_name = $this->get_User_Login;                                
 67     my @groups = $this->get_User_Groups;                                   
 68                                                                            
 69     ### Skeleton code to check if current user's groups are match with     
 70     ### specific intended group name.                                      
 71     #my $group_name = "???";                                               
 72     #my $match_group = $this->match_Group($group_name, @groups);           
 73                                                                            
 74     ### It's mandatory to call this for multi phases modules               
 75     ### to reset some of the no longer required CGI data.                  
 76     $this->SUPER::end_Task();                                              
 77                                                                            
 78     ### Put other extra end-task jobs after this line.                     
 79                                                                            
 80     ### Set to other related content.                                      
 81     #$this->set_Content("...");                                            
 82                                                                            
 83     ### Jump to other URL.                                                 
 84     #$cgi->redirect_Page($url);                                            
 85 }                                                                          
 86                                                                            
 87 ### Customize and return Table_List_Data instance that                     
 88 ### will be used for the real database operations.                         
 89 sub customize_TLD_DB_Operation {                                           
 90     my $this = shift @_;                                                   
 91                                                                            
 92     my $cgi = $this->get_CGI;                                              
 93     my $dbu = $this->get_DBU;                                              
 94     my $db_conn = $this->get_DB_Conn;                                      
 95                                                                            
 96     my $tld = $this->{tld};                                                
 97                                                                            
 98     if (defined($tld)) {                                                   
 99         ### Start manipulate $tld instance.                                
100                                                                            
101         #$tld->add_Column("new_column_name_");                             
102                                                                            
103         #for (my $i = 0; $i < $tld->get_Row_Num; $i++) {                   
104             #my $tld_data = $tld->get_Data($i, "col_name_");               
105                                                                            
106             #$tld->set_Data($i, "new_col_name_", $new_col_data);           
107         #}                                                                 
108     }                                                                      
109                                                                            
110     return $tld;                                                           
111 }                                                                          
112                                                                            
113 ### Customize and return Table_List_Data instance                          
114 ### that will be used for view purpose only.                               
115 sub customize_TLD_View {                                                   
116     my $this = shift @_;                                                   
117                                                                            
118     my $cgi = $this->get_CGI;                                              
119     my $dbu = $this->get_DBU;                                              
120     my $db_conn = $this->get_DB_Conn;                                      
121                                                                            
122     my $tld = $this->{tld};                                                
123                                                                            
124     if (defined($tld)) {                                                   
125         ### Start manipulate $tld instance.                                
126                                                                            
127         #$tld->add_Column("new_column_name_");                             
128                                                                            
129         #for (my $i = 0; $i < $tld->get_Row_Num; $i++) {                   
130             #my $tld_data = $tld->get_Data($i, "col_name_");               
131                                                                            
132             #$tld->set_Data($i, "new_col_name_", $new_col_data);           
133         #}                                                                 
134     }                                                                      
135                                                                            
136     return $tld;                                                           
137 }                                                                          
138                                                                            
139 1;