Index: /trunk/gsdl/perllib/docsave.pm
===================================================================
--- /trunk/gsdl/perllib/docsave.pm	(revision 9953)
+++ /trunk/gsdl/perllib/docsave.pm	(revision 9954)
@@ -49,13 +49,22 @@
     my $self = new docproc ();
     
-    $groupsize=1 unless defined $groupsize;
-    $service="import" unless defined $service;
+    my $collectdir = $ENV{'GSDLCOLLECTDIR'};
+
+    $outhandle = 'STDERR' unless (defined $outhandle);
+    $service   = "import" unless (defined $service);
+    $saveas    = "GA" unless (defined $saveas);
+    $groupsize = 1 unless (defined $groupsize);
 
     $self->{'collection'} = $collection;
-    if ($service eq "import"){
+    if (($service eq "import") || ($service eq "unbuild")) {
 	$self->{'archive_info'} = $info;
+	# set a default for the archive directory
+	$self->{'archive_dir'} = &util::filename_cat ($collectdir, "archives");
     } elsif ($service eq "export"){ 
 	$self->{'export_info'} = $info;
+	# set a default for the export directory
+	$self->{'export_dir'} = &util::filename_cat($collectdir, "export");
     } else {
+	print $outhandle "docsave::new Unrecongised service: $service\n";
 	return;
     }
@@ -65,20 +74,10 @@
     $self->{'keepimportstructure'} = 0;
     $self->{'groupsize'} = $groupsize;
-    $self->{'gs_count'} = 0;
-
-    $self->{'outhandle'} = 'STDERR';
-    $self->{'outhandle'} = $outhandle if defined $outhandle;
-    $self->{'service'} = $service;
-    $self->{'saveas'} = $saveas;
-
-    # set a default for the archive directory
-    if ($service eq "import"){
-	$self->{'archive_dir'} = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "archives");
-    } elsif ($service eq "export") {
-	# set a default for the export directory
-	$self->{'export_dir'} = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "export");
-    } else {
-	return;
-    }
+    $self->{'gs_count'}  = 0;
+
+    $self->{'outhandle'} = $outhandle;
+    $self->{'service'}   = $service;
+    $self->{'saveas'}    = $saveas;
+
     $self->{'sortmeta'} = undef;
     
@@ -102,4 +101,52 @@
 }
 
+sub getoutputdir {
+    my $self = shift (@_);
+
+    my $output_dir = undef;
+
+    my $service = $self->{'service'};
+
+    if (($service eq "import") || ($service eq "unbuild")) {
+	$output_dir = $self->{'archive_dir'};
+    }
+    elsif ($service eq "export") {
+	$output_dir = $self->{'export_dir'};
+    }
+    else {
+	my $outhandle = $self->{'outhandle'};
+
+	print $outhandle "docsave::getoutputdir did not recognise service ";
+	print $outhandle " '$service'. No output directory set.\n";
+    }
+
+    return $output_dir;
+}
+
+
+sub getoutputinfo {
+    my $self = shift (@_);
+
+    my $output_info = undef;
+
+    my $service = $self->{'service'};
+
+    if (($service eq "import") || ($service eq "unbuild")) {
+	$output_info = $self->{'archive_info'};
+    }
+    elsif ($service eq "export") {
+	$output_info = $self->{'export_info'};
+    }
+    else {
+	my $outhandle = $self->{'outhandle'};
+
+	print $outhandle "docsave::getoutputinfo did not recognise service ";
+	print $outhandle " '$service'. No output information available.\n";
+    }
+
+    return $output_info;
+}
+
+
 sub set_sortmeta {
     my $self = shift (@_);
@@ -122,8 +169,8 @@
  
     my $outhandle = $self->{'outhandle'};
-    my $service = $self->{'service'} || "import";
+    my $service = $self->{'service'};
 
     # Define the SaveAs Type
-    my $save_as = $self->{'saveas'} || "GA";
+    my $save_as = $self->{'saveas'};
     my $collection = $self->{'collection'};
 
@@ -136,4 +183,6 @@
     $OID = "NULL" unless defined $OID;
 
+    my $top_section = $doc_obj->get_top_section();
+
     # get document's directory
     my $doc_dir = $self->get_doc_dir ($OID, $doc_obj->get_source_filename());
@@ -141,22 +190,23 @@
     # groupsize is 1 (i.e. one document per XML file) so sortmeta 
     # may be used
-
-    if ($service eq "import") {
-	my $archive_info = $self->{'archive_info'};
-    } elsif ($service eq "export") {
-	my $export_info = $self->{'export_info'};
-    } else {
-	return;
-    }
-    
+    
+    my $output_info = $self->getoutputinfo();
+    return if (!defined $output_info);
+
+    my $output_dir = $self->getoutputdir();
+    my $working_dir = &util::filename_cat ($output_dir, $doc_dir);
+
     # copy all the associated files, add this information as metadata
     # to the document
-    if ($service eq "export" && $save_as eq "DSpace") {
-	# create handle file based on doc_dir
-
-	my $doc_handle_file
-	    = &util::filename_cat ($self->{'export_dir'},$doc_dir, "handle");
-	
-	if (!open(OUTDOC_EXPORT_HANDLE,">$doc_handle_file")){
+    if ($save_as eq "DSpace") {
+
+	# Genereate handle file 
+	# (Note: this section of code would benefit from being restructured)
+	my $doc_handle_file = &util::filename_cat ($working_dir, "handle");
+
+	my $env_hp = $ENV{'DSPACE_HANDLE_PREFIX'};
+	my $handle_prefix = (defined $env_hp) ? $env_hp : "123456789";
+
+	if (!open(OUTDOC_HANDLE,">$doc_handle_file")){
 	    print $outhandle "docsave::process could not write collection handle to file $doc_handle_file\n";
 	    return;
@@ -164,159 +214,112 @@
 
 	my ($handle) = ($doc_dir =~ m/^(.*)\.dir$/);
-	print OUTDOC_EXPORT_HANDLE "123456789/$handle\n";
-
-	close(OUTDOC_EXPORT_HANDLE);
-
-	# open contents file
-	my $doc_contents_file
-	    = &util::filename_cat ($self->{'export_dir'},$doc_dir, "contents");
-	
-	if (!open(OUTDOC_EXPORT_CONTENTS,">$doc_contents_file")){
+	print OUTDOC_HANDLE "$handle_prefix/$handle\n";
+
+	close OUTDOC_HANDLE;
+
+	# Generate contents file
+	my $doc_contents_file = &util::filename_cat ($working_dir, "contents");
+	
+	if (!open(OUTDOC_CONTENTS,">$doc_contents_file")){
 	    print $outhandle "docsave::process could not write collection contents to file $doc_contents_file\n";
 	    return;
 	} 
-	$self->process_assoc_files ($doc_obj, $doc_dir, 'docsave::OUTDOC_EXPORT_CONTENTS');
+	$self->process_assoc_files ($doc_obj, $doc_dir, 'docsave::OUTDOC_CONTENTS');
+
+	close OUTDOC_CONTENTS;
+
     } else {
 	$self->process_assoc_files ($doc_obj, $doc_dir, '');
     }
         
-    my $doc_file;
-    my $doc_mets_file;
-    my $doc_txt_file;
+    # Save the document in the requested 'save_as' format
+
+    if ($save_as eq "GA") {
+
+	my $doc_file = &util::filename_cat ($working_dir, "doc.xml");
+
+	if (!open (OUTDOC, ">$doc_file")) {
+	    print $outhandle "docsave::process could not write to file $doc_file\n";
+	    return;
+	}
+	
+	# save this document
+	$self->output_xml_header('docsave::OUTDOC');
+	$doc_obj->output_section('docsave::OUTDOC',$top_section);
+	$self->output_xml_footer('docsave::OUTDOC');
+	
+	close OUTDOC;
+    } 
+    elsif ($save_as eq "METS") {
+	
+	my $doc_txt_file = &util::filename_cat ($working_dir,"doctxt.xml");	
+
+	if (!open(OUTDOC_TXT, ">$doc_txt_file")){
+	    print $outhandle "docsave::process could not write to file $doc_txt_file\n";
+	    return;
+	}
+	
+	$self->output_txt_xml_header('docsave::OUTDOC_TXT');
+	$doc_obj->output_txt_section('docsave::OUTDOC_TXT', $top_section);
+	$self->output_txt_xml_footer('docsave::OUTDOC_TXT');
+	
+	close OUTDOC_TXT;
+	
+	# Now save the document with metadata and text structure to docmets.xml
+	
+	my $doc_mets_file = &util::filename_cat ($working_dir, "docmets.xml");
+
+	my $doc_title = $doc_obj->get_metadata_element($top_section,"dc.Title");
+	if (!defined $doc_title) {
+	    $doc_title = $doc_obj->get_metadata_element($top_section,"Title");
+	}
+
+	if (!open(OUTDOC_METS,">$doc_mets_file")){
+	    print $outhandle "docsave::process could not write to file $doc_mets_file\n";
+	    return;
+	}
+	
+	my $saveas_version = $self->{'saveas_version'};
+	$self->output_mets_xml_header('docsave::OUTDOC_METS', $OID, $doc_title);
+	$doc_obj->output_mets_section('docsave::OUTDOC_METS',$top_section,$saveas_version,$working_dir);
+	$self->output_mets_xml_footer('docsave::OUTDOC_METS');
+	
+	close OUTDOC_METS;	
+    } 
+    elsif ($save_as eq "DSpace") {
+
+	# Generate dublin_core.xml file
+	my $doc_dc_file = &util::filename_cat ($working_dir, "dublin_core.xml");
+	
+	if (!open(OUTDOC_DC,">$doc_dc_file")){
+	    print $outhandle "docsave::process could not write dublin core to file $doc_dc_file\n";
+	    return;
+	}   
+	
+	my $saveas_version = $self->{'saveas_version'};
+
+	$self->output_dc_xml_header('docsave::OUTDOC_DC', $OID);
+	$doc_obj->output_dc_section('docsave::OUTDOC_DC',$top_section);
+	$self->output_dc_xml_footer('docsave::OUTDOC_DC');
+	
+	close OUTDOC_DC;
+    } else { # save_as isn't one of the recognised types
+	print $outhandle "docsave::process unrecognised saveas type, $save_as\n";
+	return;
+    }
+
+
     my $short_doc_file;
 
-    # Save collection as either Greenstone Archive or  METS format
-    if ($service eq "import") {
-	my $doc_file 
-	    = &util::filename_cat ($self->{'archive_dir'}, $doc_dir, "doc.xml");
-
-	# define doctxt.xml file
-	my $doc_txt_file
-	    = &util::filename_cat ($self->{'archive_dir'}, $doc_dir,"doctxt.xml");
-
-	my $import_working_dir
-	    =&util::filename_cat ($self->{'archive_dir'}, $doc_dir);
-	
-	# define docmets.xml file
-	my $doc_mets_file
-	    = &util::filename_cat ($self->{'archive_dir'},$doc_dir, "docmets.xml");
-
-	if ($save_as eq "GA") {
-	    $short_doc_file = util::filename_cat ($doc_dir, "doc.xml");
-	} elsif ($save_as eq "METS") {
-	    #my $short_txt_doc_file=&util::filename_cat ($doc_dir, "doctxt.xml");
-	    $short_doc_file = &util::filename_cat ($doc_dir, "docmets.xml");
-	} else {
-	    return;
-	}
-	
-	if ($save_as eq "GA") {
-	    if (!open (OUTDOC, ">$doc_file")) {
-		print $outhandle "docsave::process could not write to file $doc_file\n";
-		return;
-	    }
-	    # save this document
-	    $self->output_xml_header('docsave::OUTDOC');
-	    $doc_obj->output_section('docsave::OUTDOC',
-				 $doc_obj->get_top_section());
-	    $self->output_xml_footer('docsave::OUTDOC');
-	    
-	    close OUTDOC;
-	} elsif ($save_as eq "METS") {
-	    # save the document without metadata:doctxt.xml
-	    
-	    if (!open(OUTDOC_TXT, ">$doc_txt_file")){
-		print $outhandle "docsave::process could not write to file $doc_txt_file\n";
-		return;
-	    }
-	    
-	    $self->output_txt_xml_header('docsave::OUTDOC_TXT');
-	    $doc_obj->output_txt_section('docsave::OUTDOC_TXT', $doc_obj->get_top_section());
-	    #$self->output_txt_xml_footer('docsave::OUTDOC_TXT');
-	    
-	    # Convert doctxt.xml file to docmets.xml
-	    if (!open(OUTDOC_METS,">$doc_mets_file")){
-		print $outhandle "docsave::process could not write to file $doc_mets_file\n";
-		return;
-	    }
-	    
-	    $self->output_mets_xml_header('docsave::OUTDOC_METS', $OID);
-	    $doc_obj->output_mets_section('docsave::OUTDOC_METS',
-					  $doc_obj->get_top_section());
-	    $self->output_mets_xml_footer('docsave::OUTDOC_METS');
-	    
-	    close OUTDOC_TXT;
-	    close OUTDOC_METS;
-	} else { # save_as isn't GA or METS
-	    print $outhandle "docsave::process unrecognised saveas type, $save_as\n";
-	    return;
-	}
-    }
-    
-    ## Export the collection to METs format or DSpace Archive Format into the export directory
-    if ($service eq "export") {
-	my $doc_dc_file;
-	my $doc_contents_file;
-
-	my $export_working_dir
-	    =&util::filename_cat ($self->{'export_dir'}, $doc_dir);
-       
-	if ($save_as eq "METS") {
-	    $doc_mets_file
-		= &util::filename_cat ($self->{'export_dir'},$doc_dir, "docmets.xml");
-	    
-	    $doc_txt_file
-		= &util::filename_cat ($self->{'export_dir'},$doc_dir, "doctxt.xml");
-	    
-	    if (!open(OUTDOC_EXPORT_TXT, ">$doc_txt_file")){
-		print $outhandle "docsave::process could not write TXT to file $doc_txt_file\n";
-		return;
-	    }
-	    
-	    $self->output_txt_xml_header('docsave::OUTDOC_EXPORT_TXT');
-	    $doc_obj->output_txt_section('docsave::OUTDOC_EXPORT_TXT', $doc_obj->get_top_section());
-	    
-	    if (!open(OUTDOC_EXPORT_METS,">$doc_mets_file")){
-		print $outhandle "docsave::process could not write METS format to file $doc_mets_file\n";
-		return;
-	    }
-	    $self->output_mets_xml_header('docsave::OUTDOC_EXPORT_METS', $OID);
-	    $doc_obj->output_mets_section('docsave::OUTDOC_EXPORT_METS',$doc_obj->get_top_section(), $export_working_dir);
-	    $self->output_mets_xml_footer('docsave::OUTDOC_EXPORT_METS');
-    
-	    close OUTDOC_EXPORT_TXT;
-	    close OUTDOC_EXPORT_METS;
-	} elsif ($save_as eq "DSpace") {
-
-	    # Generate dublin_core.xml file
-	    $doc_dc_file
-		= &util::filename_cat ($self->{'export_dir'},$doc_dir, "dublin_core.xml");
-   
-	    if (!open(OUTDOC_EXPORT_DC,">$doc_dc_file")){
-		print $outhandle "docsave::process could not write dublin core to file $doc_dc_file\n";
-		return;
-	    }   
-	   
-	    $self->output_dc_xml_header('docsave::OUTDOC_EXPORT_DC', $OID);
-	    $doc_obj->output_dc_section('docsave::OUTDOC_EXPORT_DC',$doc_obj->get_top_section(), $export_working_dir);
-	    $self->output_dc_xml_footer('docsave::OUTDOC_EXPORT_DC');
-    
-	    close OUTDOC_EXPORT_DC;
-	    close OUTDOC_EXPORT_CONTENTS;
-	} else { # save_as isn't METS or DSpace
-	    print $outhandle "docsave::process unrecognised saveas type, $save_as\n";
-	    return;
-	}
-
-	if ($save_as eq "METS") {
-	    $short_doc_file = util::filename_cat ($doc_dir, "docmets.xml");
-	} elsif ($save_as eq "DSpace") {
-	    #my $short_txt_doc_file=&util::filename_cat ($doc_dir, "doctxt.xml");
-	    $short_doc_file=&util::filename_cat ($doc_dir, "dublin_core.xml");
-	} else {
-	    return;
-	}
-	
-    }
+    if ($save_as eq "GA") {
+	$short_doc_file = util::filename_cat ($doc_dir, "doc.xml");
+    } elsif ($save_as eq "METS") {
+	$short_doc_file = &util::filename_cat ($doc_dir, "docmets.xml");
+    } elsif ($save_as eq "DSpace") {
+	$short_doc_file=&util::filename_cat ($doc_dir, "dublin_core.xml");
+    } else {
+	return;
+    }
+
     #save for later (for close_file_output())
     $self->{'short_doc_file'} = $short_doc_file;	
@@ -336,6 +339,5 @@
     my ($metadata);	
     if (defined ($self->{'sortmeta'})) {
-	$metadata = $doc_obj->get_metadata_element($doc_obj->get_top_section(),
-						   $self->{'sortmeta'});
+	$metadata = $doc_obj->get_metadata_element($top_section,$self->{'sortmeta'});
     }
     if (defined ($metadata) && $metadata) {
@@ -349,10 +351,7 @@
 	$metadata = &sorttools::format_metadata_for_sorting($self->{'sortmeta'}, $metadata, $doc_obj);
     }
-    # store reference in the archive_info and export_info
-    if ($service eq "export") {
-	$self->{'export_info'}->add_info($OID, $short_doc_file, $metadata);	
-    } elsif ($service eq "import") {
-	$self->{'archive_info'}->add_info($OID, $short_doc_file, $metadata);
-    }
+
+    # store reference in the relevant info object (archive_info,export_info,...)
+    $output_info->add_info($OID, $short_doc_file, $metadata);
 }
 
@@ -414,21 +413,14 @@
     my $self = shift (@_);
     my ($OID, $source_filename) = @_;
-    my $doc_info;
+
+    my $service = $self-> {'service'};
+
+    my $working_dir  = $self->getoutputdir();
+    my $working_info = $self->getoutputinfo();
+    return if (!defined $working_info);
+
+    my $doc_info = $working_info->get_info($OID);
     my $doc_dir = '';
-    my $service = $self-> {'service'};
-    my $working_dir;
-    my $working_info;
-
-    if ($service eq "import") {
-	$doc_info = $self->{'archive_info'}->get_info($OID);
-	$working_dir = $self->{'archive_dir'};
-	$working_info = $self->{'archive_info'};
-    } elsif ($service eq "export") {
-	$doc_info =$self->{'export_info'}->get_info($OID);
-        $working_dir = $self->{'export_dir'};
-	$working_info = $self->{'export_info'};
-    } else {
-	return;
-    }
+
     if (defined $doc_info && scalar(@$doc_info) >= 1) {
 	# this OID already has an assigned directory, use the
@@ -449,5 +441,5 @@
 	# have to get a new document directory
 
-	if ($service eq "import") {
+	if (($service eq "import") || ($service eq "unbuild")) {
 	    my $doc_dir_rest = $OID;
 	    my $doc_dir_num = 0;
@@ -465,7 +457,7 @@
 	else {
 	    # Export formats such as DSpace need the directory structure to
-	    # be flat.  This is simple to arrange (set 'doc_dir' to bit the
+	    # be flat.  This is simple to arrange (set 'doc_dir' to be the
 	    # documents OID) but breaks Windows 3.1 file system compliance.
-	    # Such a loss is not a bit thing in this situation as such
+	    # Such a loss is not a big thing in this situation as such
 	    # systems don't run on Windows 3.1 anyway.
 
@@ -485,18 +477,14 @@
 
     my $outhandle = $self->{'outhandle'};
-    
+    my $service = $self->{'service'};
+    my $save_as = $self->{'saveas'};
+
+    my $output_dir = $self->getoutputdir();
+    return if (!defined $output_dir);
+
+    my $working_dir = &util::filename_cat($output_dir, $doc_dir);
+
     my @assoc_files = ();
     my $filename;;
-    my $working_dir;
-    my $service = $self->{'service'};
-    my $save_as = $self->{'saveas'};
-
-    if ($service eq "import") {
-	$working_dir = $self->{'archive_dir'};
-    } elsif ($service eq "export"){
-	$working_dir = $self->{'export_dir'};
-    } else {
-	return;
-    }
 
     my $source_filename = $doc_obj->get_source_filename();
@@ -523,5 +511,5 @@
 	print $handle "$tail_filename\n";
 
-	$filename = &util::filename_cat($working_dir, $doc_dir, $tail_filename);
+	$filename = &util::filename_cat($working_dir, $tail_filename);
 	&util::hard_link ($source_filename, $filename);
     }
@@ -552,5 +540,5 @@
 	    }
 
-	    $filename = &util::filename_cat($working_dir, $doc_dir, $afile);
+	    $filename = &util::filename_cat($working_dir, $afile);
 
 
@@ -605,12 +593,9 @@
     }
 
-    # store reference in the archive_info and export_infor
-    if ($service eq "import") {
-	$self->{'archive_info'}->add_info($OID, $short_doc_file);
-    } elsif ($service eq "export") {
-	$self->{'export_info'}->add_info($OID, $short_doc_file);
-    } else {
-	return;
-    }
+    # store reference in relevant info object (archive_info,export_info,...)
+    my $output_info = $self->getoutputinfo();
+    return 0 if (!defined $output_info);
+    $output_info->add_info($OID, $short_doc_file);
+
     return 1;
 }
@@ -643,10 +628,25 @@
     my $self = shift(@_);
     my ($handle) = @_;
-    print $handle "<the end of the file>\n";
+    # Nothing needs to be output at present
 }
 
 sub output_mets_xml_header(){
     my $self = shift(@_);
-    my ($handle, $OID) = @_;
+    my ($handle, $OID, $doc_title) = @_;
+
+    my $version = $self->{'saveas_version'};
+
+    my $extra_attr = "";
+    if ($version eq "fedora") {	
+	my $fnamespace = $ENV{'FEDORA_PID_NAMESPACE'};
+	my $oid_namespace = (defined $fnamespace) ? $fnamespace : "test";
+
+	$extra_attr = "OBJID=\"$oid_namespace:$OID\" TYPE=\"FedoraObject\" LABEL=\"$doc_title\"";
+    }
+    else {
+	# Greenstone METS profile
+	$extra_attr = "OBJID=\"$OID:2\"";
+    }
+
 
     print $handle '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . "\n";
@@ -659,5 +659,10 @@
     print $handle '           http://www.greenstone.org/namespace/gsdlmetadata/1.0/' . "\n";
     print $handle '           http://www.greenstone.org/namespace/gsdlmetadata/1.0/gsdl_metadata.xsd"' . "\n";
-    print $handle '           OBJID="'. $OID. ':2">' . "\n";
+    print $handle "  $extra_attr>\n";
+
+    if ($version eq "fedora") {
+	print $handle '<mets:metsHdr RECORDSTATUS="A"/>'. "\n"; # A = active
+    }
+
 }
 
