################################################################
# AutoDIA - Automatic Dia XML.   (C)Copyright 2001 A Trevena   #
#                                                              #
# AutoDIA comes with ABSOLUTELY NO WARRANTY; see COPYING file  #
# This is free software, and you are welcome to redistribute   #
# it under certain conditions; see COPYING file for details    #
################################################################
package Autodia::Handler::DBI;

require Exporter;

use strict;

use warnings;
use warnings::register;

use vars qw($VERSION @ISA @EXPORT);
use Autodia::Handler;

@ISA = qw(Autodia::Handler Exporter);

use Autodia::Diagram;
use Data::Dumper;
use DBI;

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

#####################
# Constructor Methods

# new inherited from Autodia::Handler

#------------------------------------------------------------------------
# Access Methods

# parse_file inherited from Autodia::Handler

#-----------------------------------------------------------------------------
# Internal Methods

# _initialise inherited from Autodia::Handler

sub _parse_file { # parses dbi-connection string
  print "DBI.pm - parsing file\n";
  my $self     = shift();
  my $filename = shift();
  my %config   = %{$self->{Config}};

  # new dbi connection
  my $dbh = DBI->connect("DBI:$filename", $config{username}, $config{password});

  my $escape_tablenames = 0; 
  my $unescape_tablenames=0;
  my $database_type =  $dbh->get_info( 17 );

  my $schema = '' ;
  # only keep tables in schema public for PostgreSQL
  # could be given as a parameter... (+ a list of tables...)
  $schema = 'public' if (lc($database_type) =~ m/(oracle|postgres|postgresql)/);

  print "database type : $database_type $schema\n";

  # Manage database tablenames that need to be escaped before calling DBI
  # and those that need to be unescaped before calling DBI 
  $escape_tablenames = 1 if (lc($database_type) =~ m/(oracle|postgres|postgresql)/);
  $unescape_tablenames = 1 if (lc($database_type) =~ m/(mysql)/);

  print "esc : $escape_tablenames unescape $unescape_tablenames\n";
  # process tables
  # @names = $dbh->tables( $catalog, $schema, $table, $type );
  my %tables = map { $_ => 1 } $dbh->tables(undef, $schema, '%', '');
  #my %tables = map { $_ => 1 } $dbh->tables();

  warn Dumper(%tables);

  # get fields
  foreach my $table (keys %tables) { 
    
    # avoid the prefix schema as the tablename is schema.table in postgresql
    my $esc_table = $table;
    if ($escape_tablenames) { ($esc_table,$table)=split(/\./,$table); }
    $esc_table = qq{"$esc_table"} if ($escape_tablenames);
    # avoid error DBD::mysql::db column_info doesn't support table wildcard
    if ($unescape_tablenames) { $table =~ s/\`//g ; } # now $table is not escaped

    print "table $table ($schema) \n";
    # create new 'class' representing table
    my $Class = Autodia::Diagram::Class->new($table);
    
    # add 'class' to diagram
    $self->{Diagram}->add_class($Class);

    # get all column names
    #  $sth = $dbh->column_info( $catalog, $schema, $table, $column );
    #my $sth = $dbh->column_info( undef, $schema, "$table", '%' );
    my $sth = $dbh->column_info( undef, undef, "$table", '%' );
    my $row = $sth->fetchall_hashref('COLUMN_NAME');

    warn Dumper ( $row );

    foreach my $field (keys %$row ) {
      $Class->add_attribute({
			     name => $field,
			     visibility => 0,
			     type => $row->{$field}->{TYPE_NAME},
			    });

      if (my $dep = $self->_is_foreign_key($table, $field)) {
	my $Superclass = Autodia::Diagram::Superclass->new($dep);
	my $exists_already = $self->{Diagram}->add_superclass($Superclass);
	if (ref $exists_already) {
	  $Superclass = $exists_already;
	}
	# create new relationship
	my $Relationship = Autodia::Diagram::Inheritance->new($Class, $Superclass);
	# add Relationship to superclass
	$Superclass->add_inheritance($Relationship);
	# add Relationship to class
	$Class->add_inheritance($Relationship);
	# add Relationship to diagram
	$self->{Diagram}->add_inheritance($Relationship);
      }
    }

    $sth->finish;

    } # foreach $table

  $dbh->disconnect;
}

sub _is_foreign_key {
  my ($self, $table, $field) = @_;
  my $is_fk = undef;
  if (($field !~ m/$table.id/i) && ($field =~ m/^(.*)_id$/i)) {
    $is_fk = $1;
  }
  return $is_fk;
}

sub _discard_line
{
  warn "not implemented\n";
  return 0;
}

1;

###############################################################################

=head1 NAME

Autodia::Handler::DBI.pm - AutoDia handler for DBI connections

=head1 INTRODUCTION

This module parses the contents of a database through a dbi connection and builds a diagram

%language_handlers = { .. , dbi => "Autodia::Handler::DBI", .. };

=head1 CONSTRUCTION METHOD

use Autodia::Handler::DBI;

my $handler = Autodia::Handler::DBI->New(\%Config);
This creates a new handler using the Configuration hash to provide rules selected at the command line.

=head1 ACCESS METHODS

$handler->Parse($connection); # where connection includes full or dbi connection string

$handler->output(); # any arguments are ignored.

=cut






