#!/usr/bin/perl -w

use strict;
use warnings;

our $VERSION = 3.1;

=head1 NAME

load_topology

=head1 DESCRIPTION

Load the specified topology archive with the specified topology

  input file = The XML file containing the topology to add to the DB

  --output = Outputs the normalized topology file
  --db_dir = The directory of the Sleepycat Database
  --db_file = The filename of the database
  --uri = The uri of the MA to update

=cut

use XML::LibXML;
use File::Basename;
use Cwd;

use FindBin qw($Bin);
use lib "$Bin/../lib";

use perfSONAR_PS::DB::TopologyXMLDB;
use perfSONAR_PS::Client::Topology;
use perfSONAR_PS::Topology::Common qw(normalizeTopology getTopologyNamespaces);
use perfSONAR_PS::Topology::ID;
use Log::Log4perl qw(:easy);
use Getopt::Long;

my %opts;
my $help_needed;
my $DEBUGFLAG;

=head2 usage

Prints out a help message displaying the available options.

=cut

sub usage {
    print "$0: loads a topology into a database replacing the existing topology elements.\n";
    print "    [--debug] [--help] [--output=NORMALIZED_TOPOLOGY_FILE] [--db_dir=DATABASE_DIRECTORY] [--db_filename=DATABASE_FILENAME] [--uri=REMOTE_TOPOLOGY_ARCHIVE] INPUT_FILE\n";
    return;
}

my $ok = GetOptions(
    'debug'         => \$DEBUGFLAG,
    'output=s'      => \$opts{OUTPUT_FILE},
    'db_dir=s'      => \$opts{DB_DIR},
    'db_filename=s' => \$opts{DB_FILE},
    'uri=s'         => \$opts{URI},
    'help'          => \$help_needed
);

if ( not $ok or $help_needed ) {
    usage();
    exit( -1 );
}

my $input_file = shift;

if ( ( not defined $input_file ) or $input_file eq q{} or ( not -f $input_file ) ) {
    print "Error: you must specify an existing topology input file\n";
    usage();
    exit( -2 );
}

if ( ( not exists $opts{URI} ) and ( ( not exists $opts{DB_DIR} ) or ( not exists $opts{DB_FILE} ) ) ) {
    print "Error: you must specify either a URI or the Database directory/filename\n";
    usage();
    exit( -3 );
}

my $level;
if ( $DEBUGFLAG ) {
    $level = $DEBUG;
}
else {
    $level = $INFO;
}

Log::Log4perl->easy_init( $level );

my $logger = get_logger( "load_topology" );

my ( $status, $res );

my $parser = XML::LibXML->new();
my $doc    = $parser->parse_file( $input_file );

# The MA will normalize it for us, if we're not sending to the MA, we need to
# normalize unless the user has requested the normalized topology.
if ( ( not exists $opts{URI} ) or $opts{URI} eq q{} or exists $opts{OUTPUT_FILE} ) {
    ( $status, $res ) = normalizeTopology( $doc->documentElement() );
    if ( $status != 0 ) {
        $logger->debug( "Error normalizing topology: $res" );
        exit( -1 );
    }
}

if ( exists $opts{OUTPUT_FILE} and $opts{OUTPUT_FILE} ) {
    $doc->toFile( $opts{OUTPUT_FILE} );
}

my %ns;

%ns = getTopologyNamespaces();

# we probably should collect all the namespaces here
my @namespaces = $doc->documentElement()->getNamespaces();
foreach my $namespace ( @namespaces ) {
    $ns{ $namespace->prefix } = $namespace->getNamespaceURI;
}

my $client;
if ( exists $opts{URI} and $opts{URI} ) {
    $client = new perfSONAR_PS::Client::Topology( $opts{URI} );
}
else {
    if ( not -d $opts{DB_DIR} ) {
        mkdir( $opts{DB_DIR} );
    }

    $client = new perfSONAR_PS::DB::TopologyXMLDB( $opts{DB_DIR}, $opts{DB_FILE}, \%ns );
    $client->init( { directory => $opts{DB_DIR}, file => $opts{DB_FILE}, namespaces => \%ns } );
}

( $status, $res ) = $client->open;
if ( $status != 0 ) {
    $logger->debug( "Couldn't open requested database" );
    exit( -1 );
}

( $status, $res ) = $client->changeTopology( "replace", $doc->documentElement() );
if ( $status != 0 ) {
    print "Error adding topology: $res\n";
    exit( -1 );
}

exit( 0 );

__END__

=head1 SEE ALSO

L<XML::LibXML>, L<File::Basename>, L<Cwd>, L<FindBin>,
L<perfSONAR_PS::Client::Topology::XMLDB>, L<perfSONAR_PS::Client::Topology::MA>,
L<perfSONAR_PS::Topology::Common>, L<perfSONAR_PS::Topology::ID>,
L<Log::Log4perl>, L<Getopt::Long>

To join the 'perfSONAR Users' mailing list, please visit:

  https://mail.internet2.edu/wws/info/perfsonar-user

The perfSONAR-PS subversion repository is located at:

  http://anonsvn.internet2.edu/svn/perfSONAR-PS/trunk

Questions and comments can be directed to the author, or the mailing list.
Bugs, feature requests, and improvements can be directed here:

  http://code.google.com/p/perfsonar-ps/issues/list

=head1 VERSION

$Id$

=head1 AUTHOR

Aaron Brown, aaron@internet2.edu
Jason Zurawski, zurawski@internet2.edu

=head1 LICENSE

You should have received a copy of the Internet2 Intellectual Property Framework
along with this software.  If not, see
<http://www.internet2.edu/membership/ip.html>

=head1 COPYRIGHT

Copyright (c) 2004-2009, University of Delaware and Internet2

All rights reserved.

=cut
