Index: /main/trunk/greenstone2/bin/script/gti.pl
===================================================================
--- /main/trunk/greenstone2/bin/script/gti.pl	(revision 25248)
+++ /main/trunk/greenstone2/bin/script/gti.pl	(revision 25249)
@@ -131,4 +131,11 @@
 		}
     }
+    elsif ($gti_command =~ /^get-uptodate-chunks$/i) {
+		if ($module eq "gs3interface") {	   
+			print &get_uptodate_chunks_for_gs3(@gti_command_arguments);
+		} else {
+			print &get_uptodate_chunks(@gti_command_arguments);
+		}
+    }
     elsif ($gti_command =~ /^get-language-status$/i) {
 		print &get_language_status(@gti_command_arguments);       
@@ -218,4 +225,67 @@
     my $xml_response = &create_xml_response_for_all_chunks($translation_file_key, $target_file, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping, \%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);   
     
+    return $xml_response;
+}
+
+
+sub get_uptodate_chunks
+{
+    # The code of the target language (ensure it is lowercase)
+    my $target_language_code = lc(shift(@_));
+    # The key of the file to translate (ensure it is lowercase)
+    my $translation_file_key = lc(shift(@_));
+	
+    # Check that the necessary arguments were supplied
+    if (!$target_language_code || !$translation_file_key) {
+		&throw_fatal_error("Missing command argument.");
+    }
+	
+    # Get (and check) the translation configuration
+    my ($source_file, $target_file, $translation_file_type)
+	= &get_translation_configuration($target_language_code, $translation_file_key);
+	
+    # Parse the source language and target language files
+    my $source_file_path = &util::filename_cat($gsdl_root_directory, $source_file);
+    my @source_file_lines = &read_file_lines($source_file_path);
+    my %source_file_key_to_line_mapping = &build_key_to_line_mapping(\@source_file_lines, $translation_file_type);
+    
+    my $target_file_path = &util::filename_cat($gsdl_root_directory, $target_file);
+    my @target_file_lines = &read_file_lines($target_file_path);
+    my %target_file_key_to_line_mapping = &build_key_to_line_mapping(\@target_file_lines, $translation_file_type);
+	
+    # Filter out any automatically translated chunks
+    foreach my $chunk_key (keys(%source_file_key_to_line_mapping)) {
+		if (&is_chunk_automatically_translated($chunk_key, $translation_file_type)) {
+			delete $source_file_key_to_line_mapping{$chunk_key};
+			delete $target_file_key_to_line_mapping{$chunk_key};
+		}
+    }
+	
+    my %source_file_key_to_text_mapping = &build_key_to_text_mapping(\@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+    my %target_file_key_to_text_mapping = &build_key_to_text_mapping(\@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);
+    &log_message("Number of source chunks: " . scalar(keys(%source_file_key_to_text_mapping)));
+    &log_message("Number of target chunks: " . scalar(keys(%target_file_key_to_text_mapping)));
+	
+    my %source_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($source_file, \@source_file_lines, \%source_file_key_to_line_mapping, $translation_file_type);
+    my %target_file_key_to_last_update_date_mapping = &build_key_to_last_update_date_mapping($target_file, \@target_file_lines, \%target_file_key_to_line_mapping, $translation_file_type);	
+  
+
+    # Chunks needing updating are those in the target file that have been more recently edited in the source file
+    # All others are uptodate (which implies that they have certainly been translated at some point and would not be empty)
+    my @uptodate_target_file_keys = ();
+    foreach my $chunk_key (keys(%source_file_key_to_last_update_date_mapping)) {
+		my $source_chunk_last_update_date = $source_file_key_to_last_update_date_mapping{$chunk_key};
+		my $target_chunk_last_update_date = $target_file_key_to_last_update_date_mapping{$chunk_key};
+        
+        # print "key: $chunk_key\nsource date : $source_chunk_last_update_date\ntarget date : $target_chunk_last_update_date\nafter? ". &is_date_after($source_chunk_last_update_date, $target_chunk_last_update_date) . "\n\n";        
+		
+        if (defined($target_chunk_last_update_date) && !&is_date_after($source_chunk_last_update_date, $target_chunk_last_update_date)) {
+			# &log_message("Chunk with key $chunk_key needs updating.");
+			push(@uptodate_target_file_keys, $chunk_key);
+		}
+    }
+
+    my $xml_response = &create_xml_response_for_uptodate_chunks($translation_file_key, $target_file, \@uptodate_target_file_keys, \%source_file_key_to_text_mapping, \%target_file_key_to_text_mapping, \%source_file_key_to_last_update_date_mapping, \%target_file_key_to_last_update_date_mapping);   
+
     return $xml_response;
 }
@@ -1123,4 +1193,43 @@
 }
 
+sub create_xml_response_for_uptodate_chunks
+{
+    my ($translation_file_key, $target_file, $uptodate_target_files_keys, $source_files_key_to_text_mapping, $target_files_key_to_text_mapping, $source_files_key_to_last_update_date_mapping, $target_files_key_to_last_update_date_mapping) = @_;
+	
+    # Form an XML response to the command
+    my $xml_response = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
+    $xml_response .= "<GTIResponse>\n";
+    $xml_response .= "  <TranslationFile"
+	. " key=\"" . $translation_file_key . "\""
+	. " target_file_path=\"" . $target_file . "\""
+	. " num_chunks_uptodate=\"" . scalar(@$uptodate_target_files_keys) . "\"\/>\n";
+	
+	
+    # Then do chunks requiring updating
+    $xml_response .= "  <UptodateChunks size=\"" . scalar(@$uptodate_target_files_keys) . "\">\n";
+    
+	
+    # foreach my $chunk_key (@uptodate_target_file_keys) {
+    my @sorted_chunk_keys = sort (@$uptodate_target_files_keys);
+    foreach my $chunk_key (@sorted_chunk_keys) {
+		
+		my $source_file_chunk_date = $source_files_key_to_last_update_date_mapping->{$chunk_key} || "";
+		my $source_file_chunk_text = &make_text_xml_safe($source_files_key_to_text_mapping->{$chunk_key});
+		my $target_file_chunk_date = $target_files_key_to_last_update_date_mapping->{$chunk_key} || "";
+		my $target_file_chunk_text = &make_text_xml_safe($target_files_key_to_text_mapping->{$chunk_key});
+		
+		$xml_response .= "    <Chunk key=\"" . &make_text_xml_safe($chunk_key) . "\">\n";	
+		$xml_response .= "      <SourceFileText date=\"$source_file_chunk_date\">$source_file_chunk_text</SourceFileText>\n";
+		$xml_response .= "      <TargetFileText date=\"$target_file_chunk_date\">$target_file_chunk_text</TargetFileText>\n";
+		$xml_response .= "    </Chunk>\n";
+
+    }
+	
+    $xml_response .= "  </UptodateChunks>\n";
+	
+    $xml_response .= "</GTIResponse>\n";
+	
+    return $xml_response;
+}
 
 sub create_xml_response_for_all_chunks
@@ -1716,4 +1825,46 @@
 }
 
+sub get_uptodate_chunks_for_gs3
+{
+    # The code of the target language (ensure it is lowercase)
+    my $target_language_code = lc(shift(@_));
+    # The key of the file to translate (ensure it is lowercase)
+    my $translation_file_key = lc(shift(@_));
+    # The number of chunks to return (defaults to one if not specified)
+    my $num_chunks_to_return = shift(@_) || "1";
+    
+    # Check that the necessary arguments were supplied
+    if (!$target_language_code || !$translation_file_key) {
+		&throw_fatal_error("Missing command argument.");
+    }
+    
+    my %source_files_key_to_text_mapping = ();
+    my %target_files_key_to_text_mapping = ();
+    my %source_files_key_to_last_update_date_mapping = ();
+    my %target_files_key_to_last_update_date_mapping = ();
+	
+    &build_gs3_configuration($target_language_code, \%source_files_key_to_text_mapping, \%target_files_key_to_text_mapping, 
+	\%source_files_key_to_last_update_date_mapping, \%target_files_key_to_last_update_date_mapping);
+    
+
+    # Chunks needing updating are those in the target file that have been more recently edited in the source file
+    # All others are uptodate (which implies that they have certainly been translated at some point and would not be empty)
+    my @uptodate_target_file_keys = ();
+    foreach my $chunk_key (keys(%source_files_key_to_last_update_date_mapping)) {
+		my $source_chunk_last_update_date = $source_files_key_to_last_update_date_mapping{$chunk_key};
+		my $target_chunk_last_update_date = $target_files_key_to_last_update_date_mapping{$chunk_key};
+        
+        # print "key: $chunk_key\nsource date : $source_chunk_last_update_date\ntarget date : $target_chunk_last_update_date\nafter? ". &is_date_after($source_chunk_last_update_date, $target_chunk_last_update_date) . "\n\n";        
+		
+        if (defined($target_chunk_last_update_date) && !&is_date_after($source_chunk_last_update_date, $target_chunk_last_update_date)) {
+			# &log_message("Chunk with key $chunk_key needs updating.");
+			push(@uptodate_target_file_keys, $chunk_key);
+		}
+    }
+
+    my $xml_response = &create_xml_response_for_uptodate_chunks($translation_file_key, "", \@uptodate_target_file_keys, \%source_files_key_to_text_mapping, \%target_files_key_to_text_mapping, \%source_files_key_to_last_update_date_mapping, \%target_files_key_to_last_update_date_mapping);
+	
+    return $xml_response;
+}
 
 
