#!/usr/bin/perl

 #
 #  '$RCSfile$'
 #  Copyright: 2000 Regents of the University of California 
 #
 #   '$Author: daigle $'
 #     '$Date: 2010-04-14 14:31:03 -0400 (Wed, 14 Apr 2010) $'
 # '$Revision: 5311 $' 
 # 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #

package Metacat;

require 5.005_62;
use strict;
use warnings;

require Exporter;
use AutoLoader qw(AUTOLOAD);

use LWP::UserAgent;
use HTTP::Request::Common qw(POST);
use HTTP::Cookies;

our @ISA = qw(Exporter);

# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.

# This allows declaration	use Metacat ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.
our %EXPORT_TAGS = ( 'all' => [ qw(
	
) ] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw(
	
);
our $VERSION = '0.01';


# Preloaded methods go here.

#############################################################
# Constructor creates a new class instance and inits all
# of the instance variables to their proper default values,
# which can later be changed using "set_options"
#############################################################
sub new {
  my($type,$metacatUrl) = @_;
  my $cookie_jar = HTTP::Cookies->new;

  my $self = {
    metacatUrl     => $metacatUrl,
    message        => '',
    cookies        => \$cookie_jar
  };

  bless $self, $type; 
  return $self;
}

#############################################################
# subroutine to set options for the class, including the URL 
# for the Metacat database to which we would connect
#############################################################
sub set_options {
  my $self = shift;
  my %newargs = ( @_ );

  my $arg;
  foreach $arg (keys %newargs) {
    $self->{$arg} = $newargs{$arg};
  }
}

#############################################################
# subroutine to send data to metacat and get the response
# return response from metacat
#############################################################
sub sendData {
  my $self = shift;
  my %postData = ( @_ );

  $self->{'message'} = '';
  my $userAgent = new LWP::UserAgent;
  $userAgent->agent("MetacatClient/1.0");

  # determine encoding type
  my $contentType = 'application/x-www-form-urlencoded';
  if ($postData{'enctype'}) {
      $contentType = $postData{'enctype'};
      delete $postData{'enctype'};
  }

  my $request = POST("$self->{'metacatUrl'}",
                     Content_Type => $contentType,
                     Content => \%postData
                );

  # set cookies on UA object
  my $cookie_jar = $self->{'cookies'};
  $$cookie_jar->add_cookie_header($request);
  #print "Content_type:text/html\n\n";
  #print "request: " . $request->as_string();

  my $response = $userAgent->request($request);
  #print "response: " . $response->as_string();
   
  if ($response->is_success) {
    # save the cookies
    $$cookie_jar->extract_cookies($response);
    # save the metacat response message
    $self->{'message'} = $response->content;
  } else {
    #print "SendData content is: ", $response->content, "\n";
    return 0;
  } 
  return $response;
}

#############################################################
# subroutine to log into Metacat and save the cookie if the
# login is valid.  If not valid, return 0. If valid then send 
# following values to indicate user status
# 1 - user
# 2 - moderator
# 3 - administrator
# 4 - moderator and administrator
#############################################################
sub login {
  my $self = shift;
  my $username = shift;
  my $password = shift;

  my $returnval = 0;

  my %postData = ( action => 'login',
                   qformat => 'xml',
                   username => $username,
                   password => $password
                 );
  my $response = $self->sendData(%postData);
  if (($response) && $response->content =~ /<login>/) {
    $returnval = 1;
  }

  if (($response) && $response->content =~ /<isAdministrator>/) {
	if (($response) && $response->content =~ /<isModerator>/) {
    		$returnval = 4;
	} else {
		$returnval = 3;
	}
  } elsif (($response) && $response->content =~ /<isModerator>/){
	$returnval = 2;
  }

  return $returnval;
}

#############################################################
# subroutine to insert an XML document into Metacat
# If success, return 1, else return 0
#############################################################
sub insert {
  my $self = shift;
  my $docid = shift;
  my $xmldocument = shift;
  my $dtd = shift;

  my $returnval = 0;

  my %postData = ( action => 'insert',
                   docid => $docid,
                   doctext => $xmldocument
                 );
  if ($dtd) {
    $postData{'dtdtext'} = $dtd;
  }

  my $response = $self->sendData(%postData);
  if (($response) && $response->content =~ /<success>/) {
    $returnval = 1;
  } elsif (($response)) {
    $returnval = 0;
    #print "Error response from sendData!\n";
    #print $response->content, "\n";
  } else {
    $returnval = 0;
    #print "Invalid response from sendData!\n";
  }

  return $returnval;
}


#############################################################
# subroutine to set access for an XML document in Metacat
# If success, return 1, else return 0
#############################################################
sub setaccess {
  my $self = shift;
  my $docid = shift;
  my $principal = shift;
  my $permission = shift;
  my $permType = shift;
  my $permOrder = shift;

  my $returnval = 0;

  my %postData = ( action => 'setaccess',
                   docid => $docid,
		   principal => $principal,
		   permission => $permission,
		   permType => $permType,
		   permOrder => $permOrder
                 );

  my $response = $self->sendData(%postData);
  if (($response) && $response->content =~ /<success>/) {
    $returnval = 1;
  }

  return $returnval;
}



#############################################################
# subroutine to get the message returned from the last executed
# metacat action.  These are generally XML formatted messages.
#############################################################
sub getMessage {
  my $self = shift;

  return $self->{'message'};
}

package main;

use strict;

############################################################################
#
# MAIN program block
#
############################################################################

my $url = 'https://localhost/metacat/metacat/'; 
my $dn = 'uid=dataone_cn_metacat,o=DATAONE,dc=ecoinformatics,dc=org';
my $password = "";
print "Please enter dataone_cn_metacat's password: ";
chomp($password = <>);
my $docid = 'OBJECT_FORMAT_LIST.1.6';
my $principal = 'public';
my $permission = 'read';
my $permType = 'allow';
my $permOrder = 'allowFirst';
my $objectFormatListFile = "objectFormatListV2.xml";
open(DATA, $objectFormatListFile) or die "Couldn't open object format list file.";
my @lines = <DATA>;
close(DATA);
my $metadata = join('', @lines);

# Open a metacat connection and login

my $metacat = Metacat->new();

    if ($metacat) {
       $metacat->set_options( metacatUrl => $url );
    } else {
        die("Could not open connection to Metacat url: $url\n");
    }

print "attempting to login\n";
my $response = $metacat->login($dn, $password);
if (!($response)) {
	die("login $response " . $metacat->getMessage() . "\n")
}
print ($metacat->getMessage());


# Do the metacat insertion
$response = $metacat->insert($docid, $metadata);
if (!($response)) {
	die("login $response " . $metacat->getMessage() . "\n")
}

#Check the insertion succeeded, if not possibly try again with new id
print ($metacat->getMessage());


#
# Set access control permissions on the file identified
#

$response = $metacat->setaccess($docid, $principal,$permission, $permType,$permOrder);
if (!($response)) {
	die("login $response " . $metacat->getMessage() . "\n")
}
print ($metacat->getMessage());