#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
#-------------------------------------------------------
package xCAT::ExtTab;
BEGIN
{
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';

}
#  
#NO xCAT perl library routines should be used in this begin block
#(i.e. MsgUtils,Utils, etc) 
#  
#use lib "$::XCATROOT/lib/perl";

use File::Path;
%ext_tabspec=(); 
%ext_defspec=();


# loads user defined table spec. They are stored under /opt/xcat/lib/perl/xCAT_schema directory
my $path="$::XCATROOT/lib/perl/xCAT_schema";
my $filelist;  # no specific files
my @extSchema = &get_filelist($path, $filelist,"pm");
#   print "\nextSchema=@extSchema\n";

foreach (@extSchema) {
    /.*\/([^\/]*).pm$/;
    my $file=$_;
    my $modname = $1;
    no strict 'refs';
    my $warning;
    # `logger -t xCAT processing $_`; 
    eval {require($_)};
    if ($@) { 
	$warning ="Warning: The user defined database table schema file $file cannot be located or has compiling errors.\n";
        print $warning;
        `logger -p local4.warning -t xCAT $warning`; 
	next;
    }   
    if (${"xCAT_schema::" . "$modname" . "::"}{tabspec}) {
	my %tabspec=%{${"xCAT_schema::" . "$modname" . "::"}{tabspec}};
	foreach my $tabname (keys(%tabspec)) {
            if (exists($ext_tabspec{$tabname})) {
		$warning = "Warning: File $file: the table name $tabname is used by other applications. Please rename the table.\n";
                print $warning;
               `logger -p local4.warning -t xCAT $warning`; 
	    } else {
		$ext_tabspec{$tabname}=$tabspec{$tabname};
	    }
	}
    } else {
	$warning ="\n  Warning: Cannot find \%tabspec variable in the user defined database table schema file $file\n";
         print $warning;
         `logger -p local4.warning -t xCAT $warning`; 
    }
   
    #get the defspec from each file and merge them into %ext_defspec
    if (${"xCAT_schema::" . "$modname" . "::"}{defspec}) {
	my %defspec=%{${"xCAT_schema::" . "$modname" . "::"}{defspec}};
	foreach my $objname (keys(%defspec)) {
	    if (exists($defspec{$objname}->{'attrs'})) {
		if (exists($ext_defspec{$objname})) {
                    #print "insert\n";
		    my @attr_new=@{$defspec{$objname}->{'attrs'}};
		    my @attr=@{$ext_defspec{$objname}->{'attrs'}};
		    my %tmp_hash=();
		    foreach my $orig (@attr) {
			my $attrname=$orig->{attr_name};
			$tmp_hash{$attrname}=1;
		    }
		    foreach my $h (@attr_new) {
			my $attrname=$h->{attr_name};
			if (exists($tmp_hash{$attrname})) {
			    $warning= "  Warning: Conflict when adding user defined defspec from file $file. Attribute name $attrname is already defined in object $objname.  \n";
                            print $warning;
                           `logger  -p local4.warning  -t xCAT $warning`; 
			} else {
			    #print "\ngot here objname=$objname, attrname=" . $h->{attr_name} . "\n";
			    push(@{$ext_defspec{$objname}->{'attrs'}}, $h); 
			}
		    }
		} else {
		    #print "\ngot here objname=$objname, file=$file\n";
		    $ext_defspec{$objname}=$defspec{$objname};
		}	    
	    }
	}
    }   
    
} #foreach  

#print out the defspec
#print "\nexternal defspec:\n";
#foreach(%ext_defspec) {
#    print "  $_:\n";
#    my @attr=@{$ext_defspec{$_}->{'attrs'}};
#    foreach my $h (@attr) {
#	print "    " . $h->{attr_name} . "\n";
#    }
#}  

#-------------------------------------------------------
=head1 xCAT::ExtTab

    Handles user defined database tables.

=cut

#-------------------------------------------------------

=head3  updateTables

     It is called by xcatd to generate the user-defined tables 
  if they do not exist, it also updates the tables if there is 
  a schema change. 


=cut
#-------------------------------------------------------

sub updateTables
{
    #print "\nupdateTables\n";
    #print "\n";
    foreach (keys %ext_tabspec) {
	my $table= xCAT::Table->new($_,-create=>1);
        my $rc=$table->updateschema();
        $table->close();
    }
}
#--------------------------------------------------------------------------

=head3   
    Note this is a copy of the one in Table.pm but we cannot use any of the
    xCAT perl libraries in this routine,since the function was done in the
    Begin block.
    Description: get_filelist 

    Arguments:
             directory,filelist,type 
    Returns:
            The list of sql files to be processed which consists of all the
			files with <name>.sql  and <name>_<databasename>.sql
		        or 	
			files with <name>.pm  and <name>_<databasename>.pm
    Globals:

    Error:

    Example:
	my @filelist =get_filelist($directory,$filelist,$type);
            where type = "sql" or "pm"

=cut

#--------------------------------------------------------------------------------

sub get_filelist

{
    use File::Basename; 
    my $directory = shift;
    my $files     = shift;
    my $ext       = shift;
    my $dbname    = "sqlite";
    my $xcatcfg   = get_xcatcfg();

    if ($xcatcfg =~ /^DB2:/)
    {
        $dbname = "db2";
    }
    else
    {
        if ($xcatcfg =~ /^mysql:/)
        {
            $dbname = "mysql";
        }
        else
        {
            if ($xcatcfg =~ /^Pg:/)
            {
                $dbname = "pgsql";
            }
        }
    }
    $directory .= "/";

    my @filelist = ();

    my @list = glob($directory . "*.$ext");    # all files
    foreach my $file (@list)
    {
        my $filename= basename($file);  # strip filename
        my($name,$ext1) = split '\.', $filename;
        my($tmpname,$ext2) = split '\_', $name;
        if ($ext2 eq $dbname)   # matches the database
        {
            push @filelist, $file;
        }
        else
        {
            if ($ext2 eq "") # no database designated
            {
                push @filelist, $file;
            } else { # if not one of the databases, they just have _ in
                     # the file name
               if ($ext2 ne "db2" && $ext2 ne "mysql" && $ext2 ne "pgsql" && $ext2 ne "sqlite" ) {
                    push @filelist, $file;
               }
            }
        } 
         $ext2 = "";
         $ext1 = "";
    }
    return @filelist;
}
#--------------------------------------------------------------------------

=head3   

    Note this is a copy of the one in Table.pm but we cannot use any of the
    xCAT perl libraries in this routine,since the function was done in the

    Description: get_xcatcfg 

    Arguments:
              none 
    Returns:
              the database name from /etc/xcat/cfgloc or sqlite
    Globals:

    Error:

    Example:
	my $xcatcfg =get_xcatcfg();


=cut

#--------------------------------------------------------------------------------

sub get_xcatcfg
{
    my $xcatcfg = (defined $ENV{'XCATCFG'} ? $ENV{'XCATCFG'} : '');
    unless ($xcatcfg) {
        if (-r "/etc/xcat/cfgloc") {
	    my $cfgl;
	    open($cfgl,"<","/etc/xcat/cfgloc");
	    $xcatcfg = <$cfgl>;
	    close($cfgl);
	    chomp($xcatcfg);
	    $ENV{'XCATCFG'}=$xcatcfg; #Store it in env to avoid many file reads
        }
    }
    if ($xcatcfg =~ /^$/)
    {
        if (-d "/opt/xcat/cfg")
        {
            $xcatcfg = "SQLite:/opt/xcat/cfg";
        }
        else
        {
            if (-d "/etc/xcat")
            {
                $xcatcfg = "SQLite:/etc/xcat";
            }
        }
    }
    unless ($xcatcfg =~ /:/)
    {
        $xcatcfg = "SQLite:" . $xcatcfg;
    }
    return $xcatcfg;
}


1;