Index: main/trunk/greenstone2/runtime-src/src/oaiservr/dublincore.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/dublincore.cpp	(revision 21758)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/dublincore.cpp	(revision 21761)
@@ -1,4 +1,5 @@
 
 #include "dublincore.h"
+#include "gsdltools.h"
 
 dublin_core::dublin_core() : metaformat() {
@@ -72,4 +73,38 @@
 }
 
+bool dublin_core::output_custom_metadata(ostream &output, outconvertclass &outconvert, bool &headerDone, const text_t &collection, ResultDocInfo_t &docInfo) {
+  text_t value = get_metadata_value(docInfo, "srclink_file");
+  if (value.empty()) {
+    value = "gs doc"; // todo, situation where no source doc.
+  } else {
+    if (starts_with(value, "[")) {
+      // its a format statement type value eg [SourceFile], need to get the appropriate metadata
+      value = substr(findchar(value.begin(), value.end(), '[')+1,findchar(value.begin(), value.end(), ']') );
+      value = get_metadata_value(docInfo, value);
+    }
+  }
+  if (!value.empty()) {
+    text_t assocfilepath = get_metadata_value(docInfo, "assocfilepath");
+    if (!assocfilepath.empty()) {
+      value = this->oaiConfigure->getCollectionConfig("", "baseDocRoot")+"/collect/"+collection+"/index/assoc/"+assocfilepath+"/"+value;
+    } else {
+      value = "";
+    }
+    
+  } 
+  if (!value.empty()) {
+    if (!headerDone) {
+      this->output_metadata_header(output);
+      headerDone = true;
+    }
+    if (this->oaiConfigure->getOAIVersion() >= 200) { 
+      output << outconvert << "        <dc:identifier>" << xml_safe(value) << "</dc:identifier>\n";
+    }
+    else {
+      output << outconvert << "        <identifier>"  << xml_safe(value) << "</identifier>\n";
+    }
+  }
+}
+
 bool dublin_core::output_formatdata(ostream &output)
 {
Index: main/trunk/greenstone2/runtime-src/src/oaiservr/dublincore.h
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/dublincore.h	(revision 21758)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/dublincore.h	(revision 21761)
@@ -6,5 +6,5 @@
   virtual void output_metadata_header(ostream &output);
   virtual void output_metadata_footer(ostream &output);
-
+  virtual bool output_custom_metadata(ostream &output, outconvertclass &outconvert, bool &headerDone, const text_t &collection, ResultDocInfo_t &docInfo);
  public:
   dublin_core(); 
Index: main/trunk/greenstone2/runtime-src/src/oaiservr/metaformat.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/metaformat.cpp	(revision 21758)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/metaformat.cpp	(revision 21761)
@@ -39,4 +39,7 @@
 }
 
+bool metaformat::output_custom_metadata(ostream &output, outconvertclass &outconvert, bool &headerDone, const text_t &collection, ResultDocInfo_t &docInfo) {
+  return false;
+}
 bool metaformat::scan_metadata(ostream &output, const text_t &collection, ResultDocInfo_t &docInfo,
 			       bool doOutput) 
@@ -70,6 +73,4 @@
     text_t mapTo = this->get_mapping(collection, here->first);
     if (mapTo != "") {
-      // Do we actually want to do anything here? Doesn't getting here imply that this 
-      // particular metadata is stuff we don't want?
       if (doOutput) {
 	if (this->is_valid_element(mapTo)) {
@@ -85,5 +86,5 @@
 
     // Otherwise try to map the element automatically
-    // For example, dc.X is mapped to oai_dc.X (doesn't check X is a valid Dublin Core element though)
+    // For example, dc.X is mapped to oai_dc.X 
     else if (metaItem == this->formatPrefix()) {
       metaItem = substr(last+1, here->first.end()); // Get the rest of the metadata tag (it's name) but without the '.'
@@ -117,6 +118,8 @@
     return false;
   }
-  
+  // specific metadata formats might need to do some custom metadata that is not just a standard mapping. eg oai_dc outputting an identifier that is a link
+  this->output_custom_metadata(output, utf8convert, headerDone, collection, docInfo); 
   if (headerDone) {
+
     this->output_metadata_footer(output);
   }
@@ -125,4 +128,19 @@
 }
 
+text_t metaformat::get_metadata_value(ResultDocInfo_t &docInfo, const text_t &meta_name) {
+  MetadataInfo_tmap::iterator here = docInfo.metadata.find(meta_name);
+  if (here == docInfo.metadata.end()) {
+    return "";
+  }
+  return here->second.values[0];
+  
+}
+
+void metaformat::get_metadata_values(ResultDocInfo_t &docInfo, const text_t &meta_name, text_tarray &values) {
+  MetadataInfo_tmap::iterator here = docInfo.metadata.find(meta_name);
+  if (here != docInfo.metadata.end()) {
+    values = here->second.values;
+  }
+}
 
 bool metaformat::is_available(const text_t &collection, ResultDocInfo_t &docInfo)
Index: main/trunk/greenstone2/runtime-src/src/oaiservr/metaformat.h
===================================================================
--- main/trunk/greenstone2/runtime-src/src/oaiservr/metaformat.h	(revision 21758)
+++ main/trunk/greenstone2/runtime-src/src/oaiservr/metaformat.h	(revision 21761)
@@ -26,4 +26,8 @@
   virtual bool scan_metadata(ostream &output, const text_t &collection,  
 			     ResultDocInfo_t &docInfo, bool doOutput);
+  virtual bool output_custom_metadata(ostream &output, outconvertclass &outconvert, bool &headerDone, const text_t &collection, 
+			       ResultDocInfo_t &docInfo);
+  text_t get_metadata_value(ResultDocInfo_t &docInfo, const text_t &meta_name);
+  void get_metadata_values(ResultDocInfo_t &docInfo, const text_t &meta_name, text_tarray & values);
   oaiconfig *    oaiConfigure;
 
