#!/usr/bin/perl

=pod

=head1	NAME

B<Pipeline_Source>

Inserts pathname(s) into a Conductor pipeline Sources table.

=head1	SYNOPSIS

Pipeline_Source | [E<lt>B<catalog>E<gt>.]E<lt>B<pipeline>E<gt>[_Source]
[-Catalog E<lt>B<catalog>E<gt>[.E<lt>B<pipeline>E<gt>]]
[-Pipeline [E<lt>B<catalog>E<gt>.]E<lt>B<pipeline>E<gt>]
[-Id E<lt>B<source ID>E<gt>]
[-COnfiguration E<lt>B<filename>E<gt>]
[-Verbose | -Quiet]
[-Help]
E<lt>B<pathname>E<gt> [...]

=head1	OPTIONS AND ARGUMENTS

A list of one or more pathnames to be inserted into the Conductor
pipeline Sources table is specified. Relative pathnames are made absolute
before insertion by prepending the current working directory.
B<WARNING>: The current working directory is the real directory pathname
which will not be the logical pathname accessed via soft links. Each
pathname is confirmed as referring to an existing regular file.

=over

=item	-Catalog E<lt>B<catalog>E<gt>[.E<lt>B<pipeline>E<gt>]

The name of the database catalog that contains the Conductor pipeline
tables. The catalog name may be qualified by the E<lt>B<pipeline>E<gt>
name, following a '.' delimiter. Default: The E<lt>B<catalog>E<gt> name
in the command name, if present.

=item	-Pipeline [E<lt>B<catalog>E<gt>.]E<lt>B<pipeline>E<gt>

The name of the Conductor pipeline to receive Source_Pathname entries.
The pipeline name may be qualified by the E<lt>B<catalog>E<gt> name,
preceeding a '.' delimiter. Default: The command name, or that part of the
command name preceding a "_Source" suffix. B<Note>: If the command name
provides the pipeline name, it may also use the
E<lt>B<catalog>E<gt>.E<lt>B<pipeline>E<gt> notation.

=item	-Id E<lt>B<source ID>E<gt>

If this option is specified the Source_ID field of the source record will be
set to the E<lt>source IDE<gt> value. Typically, this option, when used,
is specified for each E<lt>pathnameE<gt> specified; each E<lt>source IDE<gt>
will be paired with a E<lt>pathnameE<gt> according to the order in which
they occur on the command line. If only one E<lt>source IDE<gt> is
specified for multiple E<lt>pathnamesE<gt>, then it is applied to all; any
other mismatch will cause a syntax error. If no E<lt>source IDE<gt> is
specified none will be applied.

=item	-COnfiguration E<lt>B<filename>E<gt>

The value of an environment variable named
E<lt>B<pipeline>E<gt>_CONFIG_DIR will be used, if present, as the name
of the directory where the configuration file is to be found if the
specified configuration filename is not an absolute pathname; otherwise
the current working directory will be tried. Default:
E<lt>B<pipeline>E<gt>.conf.

=item	-Verbose | -Quiet

Verbose operation provides details about what is being done.
Quiet operation minimizes messages. Default: Quiet.

=item	-Help

The man page for this procedure is listed.

=back

=head1	DESCRIPTION

The list of pathnames specified on the command line will be inserted
into the Source_Pathname field of the E<lt>B<pipeline>E<gt>_Sources
table in the E<lt>B<catalog>E<gt> database catalog. If one or -Id
E<lt>B<source ID>E<gt> values are specified these values will be used to
set the Source_ID field of the inserted records. The configuration file
must contain the appropriate database access information need by the
Update_DB utility.

=head1	Exit Status

=over

=item	E<48> - Success

The database table insert(s) completed successfully.

=item	E<49> - Bad command line syntax

A command line syntax usage message will be provided.

=item	E<50> - No such file

A pathname to a non-existant file, or a file that is not a regular file
(e.g. a directory pathname may not be used), was specified. This applies
to both source and configuration file pathnames.

=item	E<52> - Database insert(s) failed

The database table insert(s) did not complete successfully. A report
from the Update_DB procedure will be provided.

=back

=head1	Author

Bradford Castalia, UA/PIRL

=head1	Copyright

Copyright (C) 2004, 2005 Arizona Board of Regents on behalf of the
Planetary Image Research Laboratory, Lunar and Planetary Laboratory at
the University of Arizona.

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License, version 2, as
published by the Free Software Foundation.

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.

=head1	Version

1.18 2006/01/20 05:46:52

=cut

#	CVS ID: Pipeline_Source,v 1.18 2006/01/20 05:46:52 castalia Exp
#===============================================================================
$CVS_ID = 'Pipeline_Source (1.18 2006/01/20 05:46:52)';

($Command_Name = $0) =~ s|.*/(\S+)$|$1|;
print "$Command_Name - $CVS_ID\n";

#	Defaults:

#	Assume that the command name is the pipeline name.
$DEFAULT_PIPELINE	= $Command_Name;
$DEFAULT_PIPELINE	=~ s/(.+)_Source$/$1/
	if ($DEFAULT_PIPELINE =~ /.+_Source$/);

$DEFAULT_CATALOG	= "Proc_Test";

$CONFIG_DIR_ENV		= "_CONFIG_DIR";

@Update_Operation	= ("Update_DB");
$PATHNAME_FIELD     = "Source_Pathname";
$SOURCE_ID_FIELD	= "Source_ID";

#	Exit status values:
$SUCCESS			= 0;
$BAD_SYNTAX			= 1;
$NO_SUCH_FILE		= 2;
$UPDATE_FAILED		= 4;

#-------------------------------------------------------------------------------
#	Command line arguments:

use Pod::Usage;

pod2usage
	(
	-verbose => 0,
	-exitval => $BAD_SYNTAX
	)
	unless @ARGV;

while ($option = shift @ARGV)
	{
	#	N.B.: Must come before -Catalog option.
	if ($option =~ /^-[Cc][Oo]/)
		{
		#	Configuration file.
		pod2usage
			(
			-message => "$Command_Name: Missing configuration filename.\n",
			-verbose => 0,
			-exitval => $BAD_SYNTAX
			)
			unless (@ARGV && $ARGV[0] !~ /^-/);
		$Config_Pathname = shift @ARGV;
		next;
		}
	if ($option =~ /^-[Cc]/ ||
		$option =~ /^-[Dd]/)
		{
		#	Catalog (or Database).
		pod2usage
			(
			-message => "$Command_Name: Missing database catalog name.\n",
			-verbose => 0,
			-exitval => $BAD_SYNTAX
			)
			unless (@ARGV && $ARGV[0] !~ /^-/);
		$catalog = catalog_name ($option = shift @ARGV);
		$catalog = $option
			unless $catalog;
		Multiple_Catalogs:
		pod2usage
			(
			-message => "$Command_Name: Multiple catalogs specified - ".
				"$Catalog and $catalog\n",
			-verbose => 0,
			-exitval => $BAD_SYNTAX
			)
			if $Catalog && ($Catalog ne $catalog);
		$Catalog = $catalog;

		#	Check for pipeline name.
		$pipeline = pipeline_name ($option);
		goto Multiple_Pipelines
			if $pipeline && $Pipeline && ($pipeline ne $Pipeline);
		$Pipeline = $pipeline
			if $pipeline;
		next;
		}
	if ($option =~ /^-[Pp]/)
		{
		#	Pipeline name.
		pod2usage
			(
			-message => "$Command_Name: Missing pipeline name.\n",
			-verbose => 0,
			-exitval => $BAD_SYNTAX
			)
			unless (@ARGV && $ARGV[0] !~ /^-/);
		$pipeline = pipeline_name ($option = shift @ARGV);
		$pipeline = $option
			unless $pipeline;
		Multiple_Pipelines:
		pod2usage
			(
			-message => "$Command_Name: Multiple pipelines specified - ".
				"$Pipeline and $pipeline\n",
			-verbose => 0,
			-exitval => $BAD_SYNTAX
			)
			if $Pipeline && ($Pipeline ne $pipeline);
		$Pipeline = $pipeline;

		#	Check for catalog name.
		$catalog = catalog_name ($option);
		goto Multiple_Catalogs
			if $catalog && $Catalog && ($catalog ne $Catalog);
		$Catalog = $catalog
			if $catalog;
		next;
		}
	if ($option =~ /^-[Ii]/)
		{
		#	Source ID.
		pod2usage
			(
			-message => "$Command_Name: Missing source ID.\n",
			-verbose => 0,
			-exitval => $BAD_SYNTAX
			)
			unless (@ARGV && $ARGV[0] !~ /^-/);
		push @Source_IDs, shift @ARGV;
		next;
		}
	if ($option =~ /^-[Vv]/)
		{
		#	Verbose.
		$Verbose = 1;
		next;
		}
	if ($option =~ /^-[Qq]/)
		{
		#	Quiet.
		$Verbose = 0;
		next;
		}

	#	Help.
	pod2usage
		(
		-verbose => 2,
		-exitval => 0
		)
		if ($option =~ /^-[Hh]/);

	pod2usage
		(
		-message => "$Command_Name: Unknown option \"$option\"\n",
		-verbose => 0,
		-exitval => $BAD_SYNTAX
		)
		if ($option =~ /^-/);

	#	Source pathname.
	push @Filenames, $option;
	}

#-------------------------------------------------------------------------------
#	Post-command initialization.

#	Pipeline name.
if (! $Pipeline)
	{
	$pipeline = pipeline_name ($DEFAULT_PIPELINE);
	$pipeline = $DEFAULT_PIPELINE
		unless $pipeline;
	$Pipeline = $pipeline;

	#	Check for catalog name.
	$catalog = catalog_name ($DEFAULT_PIPELINE);
	goto Multiple_Catalogs
		if $catalog && $Catalog && ($catalog ne $Catalog);
	$Catalog = $catalog
		if $catalog;
	}

#	Database catalog name.
if (! $Catalog)
	{
	#	Try to find a catalog name in the default pipeline name.
	$Catalog = catalog_name ($DEFAULT_PIPELINE);
	pod2usage
		(
		-message => "$Command_Name: A database catalog name must be specified.\n",
		-verbose => 0,
		-exitval => $BAD_SYNTAX
		)
		unless $Catalog;
	}


#	Configuration file.
$Config_Pathname = $Pipeline.".conf"
	unless $Config_Pathname;

use File::Spec;
if (! File::Spec->file_name_is_absolute ($Config_Pathname))
	{
	#	Relative pathname.
	#	Check for a configuration directory environment variable.
	$Configuration_Dir = $ENV{$Pipeline . $CONFIG_DIR_ENV};
	$Config_Pathname = "$Configuration_Dir/$Config_Pathname"
		if $Configuration_Dir;
	#	Ensure absolute pathname.
	$Config_Pathname = File::Spec->rel2abs ($Config_Pathname);
	}


#	Check the filenames.
pod2usage
	(
	-message => "$Command_Name: At least one pathname must be specified.\n",
	-verbose => 0,
	-exitval => $BAD_SYNTAX
	)
	unless @Filenames;

pod2usage
	(
	-message => "$Command_Name: The number of pathnames (" . scalar @Filenames
		. ") and source IDs (" . scalar @Source_IDs . ") do not match.\n",
	-verbose => 0,
	-exitval => $BAD_SYNTAX
	)
	if (@Source_IDs &&
		@Source_IDs != 1 &&
		@Source_IDs != @Filenames);
$Source_ID = shift @Source_IDs
	if @Source_IDs == 1;

foreach $filename (@Filenames)
	{
	#	Ensure absolute pathname.
	$filename = File::Spec->rel2abs ($filename);
	if (! -f $filename)
		{
		print STDERR
			"$Command_Name: No such file - $filename\n";
		exit ($NO_SUCH_FILE);
		}
	push @Pathnames, $filename;
	push @Source_IDs, $Source_ID
		if $Source_ID;
	}

#-------------------------------------------------------------------------------
#	Database update operation.

push @Update_Operation,
	'-Verbose'
	if $Verbose;
push @Update_Operation,
	'-Configuration',	$Config_Pathname,
	'-Table',			$Catalog.'.'.$Pipeline."_Sources";

foreach $Pathname (@Pathnames)
	{
	push @Update_Operation, "$PATHNAME_FIELD=$Pathname";
	push @Update_Operation, "$SOURCE_ID_FIELD=".shift @Source_IDs
		if @Source_IDs;
	print "\n@Update_Operation\n"
		if $Verbose;

	#	Issue the command to the system.
	$exit_status = system @Update_Operation;
	if ($exit_status == -1)
		{
		print STDERR
			"$Command_Name: The command could not be executed!\n";
		print STDERR "\n@Update_Operation\n"
			unless $Verbose;
		exit ($UPDATE_FAILED);
		}
	elsif (($exit_status >>= 8) != 1)
		{
		print STDERR
			"$Command_Name: Update failed - exit status $exit_status.\n";
		print STDERR "\n@Update_Operation\n"
			unless $Verbose;
		exit ($UPDATE_FAILED);
		}
	pop @Update_Operation;
	pop @Update_Operation
		if @Source_IDs;
	}

exit ($SUCCESS);


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

sub catalog_name
{
my ($name) = @_;
return (($index = index ($name, '.')) > 0) ?
	substr ($name, 0, $index) : undef;
}


sub pipeline_name
{
my ($name) = @_;
return (($index = index ($name, '.')) >= 0 && $index < (length ($name) - 1)) ?
	substr ($name, $index + 1) : undef;
}
