Index: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/OAIReceptionist.java
===================================================================
--- main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/OAIReceptionist.java	(revision 27671)
+++ main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/OAIReceptionist.java	(revision 27672)
@@ -26,4 +26,7 @@
   /** Instead of a config_params object, only a site_name is needed by oai receptionist. */
   protected String site_name = null;
+  /** The unique  repository identifier */
+  protected String repository_id = null;
+  
   /** container Document to create XML Nodes for requests sent to message router
    *  Not used for response 
@@ -43,4 +46,14 @@
   protected ModuleInterface mr = null;
   
+
+  // Some of the data/responses will not change while the servlet is running, so
+  // we can cache them
+  
+  /** A list of all the collections available to this OAI server */
+  protected NodeList collection_list = null;
+
+  /** The identify response */
+  protected Element identify_response = null;
+  
   public OAIReceptionist() {
     this.converter = new XMLConverter();
@@ -74,4 +87,7 @@
     resume_after = getResumeAfter();
     
+    repository_id = getRepositoryId(); 
+    collection_list = getOAICollectionList();
+
     //clear out expired resumption tokens stored in OAIResumptionToken.xml
     OAIXML.init();
@@ -190,4 +206,11 @@
     return -1;
   }
+  private String getRepositoryId() {
+    Element ri = (Element)GSXML.getChildByTagName(oai_config, OAIXML.REPOSITORY_ID);
+    if (ri != null) { 
+      return GSXML.getNodeText(ri);
+    }
+    return "";
+  }
   /** method to compose a set element
    */
@@ -198,7 +221,5 @@
     Element list_sets_elem = OAIXML.createElement(OAIXML.LIST_SETS);
 
-    //ask the message router for a list of oai collections
-    NodeList oai_coll = getOAICollectionList();
-    int oai_coll_size = oai_coll.getLength();
+    int oai_coll_size = collection_list.getLength(); 
     if (oai_coll_size == 0) {
       return getMessage(list_sets_elem);
@@ -229,10 +250,10 @@
         //no resumeptionToken stored in OAIConfig.xml.
         //As long as the verb is 'ListSets', we ignore the rest of the parameters
-        getSets(list_sets_elem, oai_coll, 0, oai_coll_size);
+        getSets(list_sets_elem, collection_list, 0, oai_coll_size);
         return getMessage(list_sets_elem);
       }
       
       //append required sets to list_sets_elem (may be a complete or incomplete list)
-      getSets(list_sets_elem, oai_coll, 0, smaller);
+      getSets(list_sets_elem, collection_list, 0, smaller);
       
       if(oai_coll_size > resume_after) {
@@ -272,5 +293,5 @@
       //Yes, we are.
       //append required sets to list_sets_elem (list is complete)
-      getSets(list_sets_elem, oai_coll, cursor, oai_coll_size);
+      getSets(list_sets_elem, collection_list, cursor, oai_coll_size);
       //An incomplete list is sent; append a resumptionToken element
       token_elem = createResumptionTokenElement(oai_coll_size, cursor, -1, false);
@@ -279,5 +300,5 @@
       //No, we are not.
       //append required sets to list_sets_elem (list is incomplete)
-      getSets(list_sets_elem, oai_coll, cursor, cursor + resume_after);
+      getSets(list_sets_elem, collection_list, cursor, cursor + resume_after);
       token_elem = createResumptionTokenElement(oai_coll_size, cursor, cursor + resume_after, true);
       //store this token
@@ -377,6 +398,6 @@
 
     //ask the message router for a list of oai collections
-    NodeList oai_coll = getOAICollectionList();
-    int oai_coll_size = oai_coll.getLength();
+    //NodeList oai_coll = collection_list; //getOAICollectionList();
+    int oai_coll_size = collection_list.getLength();
     if (oai_coll_size == 0) {
       logger.info("returned oai collection list is empty");
@@ -396,5 +417,5 @@
 
       for(int i=0; i<oai_coll_size; i++) {
-        if(set_spec_str.equals(((Element)oai_coll.item(i)).getAttribute(OAIXML.NAME))) {
+        if(set_spec_str.equals(((Element)collection_list.item(i)).getAttribute(OAIXML.NAME))) {
           set_supported = true;
         }
@@ -452,5 +473,5 @@
           }
         }
-        String full_name = ((Element)oai_coll.item(i)).getAttribute(OAIXML.NAME);
+        String full_name = ((Element)collection_list.item(i)).getAttribute(OAIXML.NAME);
         coll_name = full_name.substring(full_name.indexOf(":") + 1);
         req.setAttribute(OAIXML.TO, coll_name + "/" + verb);
@@ -589,6 +610,6 @@
     
     //ask the message router for a list of oai collections
-    NodeList oai_coll = getOAICollectionList();
-    int oai_coll_size = oai_coll.getLength();
+    //NodeList oai_coll = getOAICollectionList();
+    int oai_coll_size = collection_list.getLength();
     if (oai_coll_size == 0) {
       logger.info("returned oai collection list is empty");
@@ -610,5 +631,5 @@
 
       for(int i=0; i<oai_coll_size; i++) {
-        if(set_spec_str.equals(((Element)oai_coll.item(i)).getAttribute(OAIXML.NAME))) {
+        if(set_spec_str.equals(((Element)collection_list.item(i)).getAttribute(OAIXML.NAME))) {
           set_supported = true;
         }
@@ -701,5 +722,5 @@
           }
         }
-        String full_name = ((Element)oai_coll.item(i)).getAttribute(OAIXML.NAME);
+        String full_name = ((Element)collection_list.item(i)).getAttribute(OAIXML.NAME);
         coll_name = full_name.substring(full_name.indexOf(":") + 1);
         req.setAttribute(OAIXML.TO, coll_name + "/" + verb);
@@ -832,31 +853,30 @@
       //this is requesting metadata formats for the whole repository
       //read the oaiConfig.xml file, return the metadata formats specified there.
-      Element oai_config = OAIXML.getOAIConfigXML();
-      if (oai_config == null) {
-        return getMessage(OAIXML.createErrorElement(OAIXML.ERROR, OAIXML.SERVICE_UNAVAILABLE));
-      } else {
-        Element format_list = (Element)GSXML.getChildByTagName(oai_config, OAIXML.LIST_METADATA_FORMATS);
-        if(format_list == null) {
-          logger.error("OAIConfig.xml must contain the supported metadata formats");
-          return getMessage(list_metadata_formats);
+      Element format_list = (Element)GSXML.getChildByTagName(oai_config, OAIXML.LIST_METADATA_FORMATS);
+      if(format_list == null) {
+	logger.error("OAIConfig.xml must contain the supported metadata formats");
+	return getMessage(list_metadata_formats);
+      }
+      NodeList formats = format_list.getElementsByTagName(OAIXML.METADATA_FORMAT);
+      for(int i=0; i<formats.getLength(); i++) {
+	Element meta_fmt = OAIXML.createElement(OAIXML.METADATA_FORMAT);
+	Element first_meta_format = (Element)formats.item(i);
+	//the element also contains mappings, but we don't want them
+	meta_fmt.appendChild(meta_fmt.getOwnerDocument().importNode(GSXML.getChildByTagName(first_meta_format, OAIXML.METADATA_PREFIX), true));
+	meta_fmt.appendChild(meta_fmt.getOwnerDocument().importNode(GSXML.getChildByTagName(first_meta_format, OAIXML.SCHEMA), true));
+	meta_fmt.appendChild(meta_fmt.getOwnerDocument().importNode(GSXML.getChildByTagName(first_meta_format, OAIXML.METADATA_NAMESPACE), true));
+	list_metadata_formats.appendChild(meta_fmt);
         }
-        NodeList formats = format_list.getElementsByTagName(OAIXML.METADATA_FORMAT);
-        for(int i=0; i<formats.getLength(); i++) {
-          Element meta_fmt = OAIXML.createElement(OAIXML.METADATA_FORMAT);
-          Element first_meta_format = (Element)formats.item(i);
-          //the element also contains mappings, but we don't want them
-          meta_fmt.appendChild(meta_fmt.getOwnerDocument().importNode(GSXML.getChildByTagName(first_meta_format, OAIXML.METADATA_PREFIX), true));
-          meta_fmt.appendChild(meta_fmt.getOwnerDocument().importNode(GSXML.getChildByTagName(first_meta_format, OAIXML.SCHEMA), true));
-          meta_fmt.appendChild(meta_fmt.getOwnerDocument().importNode(GSXML.getChildByTagName(first_meta_format, OAIXML.METADATA_NAMESPACE), true));
-          list_metadata_formats.appendChild(meta_fmt);
-        }
-        return getMessage(list_metadata_formats);
-      }
+      return getMessage(list_metadata_formats);
       
-    } else if (params.getLength() > 1) {
+      
+    } 
+
+    if (params.getLength() > 1) {
       //Bad argument. Can't be more than one parameters for ListMetadataFormats verb
       return getMessage(OAIXML.createErrorElement(OAIXML.BAD_ARGUMENT, ""));
-    } else {
-      // This is a request for the metadata of a particular item with an identifier
+    } 
+    
+    // This is a request for the metadata of a particular item with an identifier
       /**the request xml is in the form: <request>
        *                                   <param name=.../>
@@ -904,7 +924,9 @@
 	return converter.nodeToElement(result_node);
       }
-    }
-    
-  }
+  
+    
+  }
+
+
   private void appendParam(Element req, String name, String value) {    
         Element param = req.getOwnerDocument().createElement(OAIXML.PARAM);
@@ -913,23 +935,31 @@
         req.appendChild(param);
   }
-  private void copyElement(Element identify, String tag_name) {
-    Element from_repository_name = (Element)GSXML.getChildByTagName(oai_config, tag_name);
-    if(from_repository_name != null) {
-      Element this_repository_name = OAIXML.createElement(tag_name);
-      GSXML.setNodeText(this_repository_name, GSXML.getNodeText(from_repository_name));
-      identify.appendChild(this_repository_name);
-    }
-  }
+  private void copyNamedElementfromConfig(Element to_elem, String element_name) {
+    Element original_element = (Element)GSXML.getChildByTagName(oai_config, element_name);
+    if(original_element != null) {
+      copyNode(to_elem, original_element);
+    }
+  }
+
+  private void copyNode(Element to_elem, Node original_element) {
+    to_elem.appendChild(to_elem.getOwnerDocument().importNode(original_element, true));
+
+  }
+
   private Element doIdentify() {
     //The validation for this verb has been done in OAIServer.validate(). So no bother here.
     logger.info("");
+    if (this.identify_response != null) {
+      // we have already created it
+      return getMessage(this.identify_response);
+    }
     
     Element identify = OAIXML.createElement(OAIXML.IDENTIFY);
     //do the repository name
-    copyElement(identify, OAIXML.REPOSITORY_NAME);
+    copyNamedElementfromConfig(identify, OAIXML.REPOSITORY_NAME);
     //do the baseurl
-    copyElement(identify, OAIXML.BASE_URL);
+    copyNamedElementfromConfig(identify, OAIXML.BASE_URL);
     //do the protocol version
-    copyElement(identify, OAIXML.PROTOCOL_VERSION);
+    copyNamedElementfromConfig(identify, OAIXML.PROTOCOL_VERSION);
         
     //There can be more than one admin email according to the OAI specification
@@ -941,5 +971,5 @@
     }
     for (int i=0; i<num_admin; i++) {
-      copyElement(identify, OAIXML.ADMIN_EMAIL);
+      copyNode(identify, admin_emails.item(i));
     }
 
@@ -947,6 +977,6 @@
     //send request to mr to search through the earliest datestamp amongst all oai collections in the repository.
     //ask the message router for a list of oai collections
-    NodeList oai_coll = getOAICollectionList();
-    long earliestDatestamp = getEarliestDateStamp(oai_coll);
+    //NodeList oai_coll = getOAICollectionList();
+    long earliestDatestamp = getEarliestDateStamp(collection_list);
     String earliestDatestamp_str = OAIXML.getTime(earliestDatestamp);
     Element earliestDatestamp_elem = OAIXML.createElement(OAIXML.EARLIEST_DATESTAMP);
@@ -955,8 +985,28 @@
 
     //do the deletedRecord
-    copyElement(identify, OAIXML.DELETED_RECORD);
+    copyNamedElementfromConfig(identify, OAIXML.DELETED_RECORD);
     //do the granularity
-    copyElement(identify, OAIXML.GRANULARITY);
-        
+    copyNamedElementfromConfig(identify, OAIXML.GRANULARITY);
+     
+    // output the oai identifier
+    Element description = OAIXML.createElement(OAIXML.DESCRIPTION);
+    identify.appendChild(description);
+    Element oaiIdentifier = OAIXML.createOAIIdentifierXML(repository_id, "lucene-jdbm-demo", "ec159e");
+    description.appendChild(oaiIdentifier);
+
+    // if there are any oaiInfo metadata, add them in too.
+    Element info = (Element)GSXML.getChildByTagName(oai_config, OAIXML.OAI_INFO);
+    if (info != null) {
+      NodeList meta = GSXML.getChildrenByTagName(info, OAIXML.INFO_METADATA);
+      if (meta != null && meta.getLength() > 0) {
+	Element gsdl = OAIXML.createGSDLElement();
+	description.appendChild(gsdl);
+	for (int m = 0; m<meta.getLength(); m++) {
+	  copyNode(gsdl, meta.item(m));
+	}
+	
+      }
+    }
+    this.identify_response = identify;
     return getMessage(identify);
   }
