root/greenstone3/trunk/src/java/org/greenstone/gsdl3/service/OAIPMH.java @ 16871

Revision 16871, 28.7 KB (checked in by kjdon, 2 years ago)

added type=oai to all oai service elements

Line 
1/*
2 *    OAIPMH.java
3 *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
4 *
5 *    This program is free software; you can redistribute it and/or modify
6 *    it under the terms of the GNU General Public License as published by
7 *    the Free Software Foundation; either version 2 of the License, or
8 *    (at your option) any later version.
9 *
10 *    This program is distributed in the hope that it will be useful,
11 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *    GNU General Public License for more details.
14 *
15 *    You should have received a copy of the GNU General Public License
16 *    along with this program; if not, write to the Free Software
17 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.service;
20
21// Greenstone classes
22import org.greenstone.gsdl3.core.GSException;
23import org.greenstone.gsdl3.util.GSXML;
24import org.greenstone.gsdl3.util.OAIXML;
25import org.greenstone.gsdl3.util.OID;
26import org.greenstone.gsdl3.util.GSFile;
27import org.greenstone.gsdl3.util.XMLConverter;
28
29import org.greenstone.gsdl3.util.SimpleCollectionDatabase;
30import org.greenstone.gsdl3.util.DBInfo;
31// XML classes
32import org.w3c.dom.Document;
33import org.w3c.dom.Element;
34import org.w3c.dom.NodeList;
35
36// General Java classes
37import java.io.File;
38import java.util.StringTokenizer;
39import java.util.Vector;
40import java.util.Set;
41import java.util.Iterator;
42import java.util.ArrayList;
43import java.util.Date;
44import java.util.HashMap;
45import java.util.Map.Entry;
46
47import org.apache.log4j.Logger;
48
49/** Implements the oai metadata retrieval service for GS3 collections.
50 *  Dig into each collection's database and retrieve the metadata
51 *
52 * @author <a href="mailto:xiao@cs.waikato.ac.nz">Xiao</a>
53 */
54
55public class OAIPMH extends ServiceRack {
56 
57  static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.OAIPMH.class.getName());
58 
59  protected SimpleCollectionDatabase coll_db = null;
60 
61  protected String site_name = "";
62  protected String coll_name = "";
63  protected Element coll_config_xml = null;
64 
65  /** constructor */
66  public OAIPMH() {
67
68  }
69 
70  public void cleanUp() {
71    super.cleanUp();//??
72    this.coll_db.closeDatabase();
73  }
74  /** configure this service */
75  public boolean configure(Element info, Element extra_info) {
76    if (!super.configure(info, extra_info)){
77      logger.info("Configuring ServiceRack.java returns false.");
78      return false;
79    }
80   
81    //get the names from ServiceRack.java
82    site_name = this.router.getSiteName();
83    coll_name = this.cluster_name;
84    //get the collection-specific configurations from collectionConfig.xml
85    coll_config_xml = OAIXML.getCollectionConfigXML(site_name, coll_name);
86   
87    logger.info("Configuring OAIPMH...");
88    // this call passes the indexStem in of ServiceRack element in buildConfig.xml to the super class.
89    this.config_info = info;
90   
91    // the index stem is either specified in the buildConfig.xml file or uses the collection name
92    Element index_stem_elem = (Element) GSXML.getChildByTagName(info, GSXML.INDEX_STEM_ELEM);
93    String index_stem = null;
94    if (index_stem_elem != null) {
95      index_stem = index_stem_elem.getAttribute(GSXML.NAME_ATT);
96    }
97    if (index_stem == null || index_stem.equals("")) {
98      index_stem = this.cluster_name;
99    }
100 
101    // find out what kind of database we have
102    Element database_type_elem = (Element) GSXML.getChildByTagName(info, GSXML.DATABASE_TYPE_ELEM);
103    String database_type = null;
104    if (database_type_elem != null) {
105      database_type = database_type_elem.getAttribute(GSXML.NAME_ATT);
106    }
107    if (database_type == null || database_type.equals("")) {
108      database_type = "gdbm"; // the default
109    }
110    coll_db = new SimpleCollectionDatabase(database_type);
111    if (coll_db == null) {
112      logger.error("Couldn't create the collection database of type "+database_type);
113      return false;
114    }
115   
116    // Open database for querying
117    String coll_db_file = GSFile.collectionDatabaseFile(this.site_home, this.cluster_name, index_stem, database_type);
118    if (!this.coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ)) {
119      logger.error("Could not open collection database!");
120      return false;
121    }
122   
123    // the short_service_info is used by the message router to find the method names,
124    //so we just use the doc variable in class ServiceRack to create the xml; but
125    // in each method we will use OAIXML to create the response xml
126    // set up short_service_info_ - just the name
127 
128    Element identify = this.doc.createElement(OAIXML.SERVICE);
129
130    identify.setAttribute(OAIXML.NAME, OAIXML.IDENTIFY);
131    identify.setAttribute(GSXML.TYPE_ATT, "oai");
132    this.short_service_info.appendChild(identify);
133
134    Element list_records = this.doc.createElement(OAIXML.SERVICE);
135    list_records.setAttribute(OAIXML.NAME, OAIXML.LIST_RECORDS);
136    list_records.setAttribute(GSXML.TYPE_ATT, "oai");
137    this.short_service_info.appendChild(list_records);
138
139    Element list_identifiers = this.doc.createElement(OAIXML.SERVICE);
140    list_identifiers.setAttribute(OAIXML.NAME, OAIXML.LIST_IDENTIFIERS);
141    list_identifiers.setAttribute(GSXML.TYPE_ATT, "oai");
142    this.short_service_info.appendChild(list_identifiers);
143   
144    Element list_sets = this.doc.createElement(OAIXML.SERVICE);
145    list_sets.setAttribute(OAIXML.NAME, OAIXML.LIST_SETS);
146    list_sets.setAttribute(GSXML.TYPE_ATT, "oai");
147    this.short_service_info.appendChild(list_sets);
148   
149    Element list_metadata_formats = this.doc.createElement(OAIXML.SERVICE);
150    list_metadata_formats.setAttribute(OAIXML.NAME, OAIXML.LIST_METADATA_FORMATS);
151    list_metadata_formats.setAttribute(GSXML.TYPE_ATT, "oai");
152    this.short_service_info.appendChild(list_metadata_formats);
153
154    Element get_record = this.doc.createElement(OAIXML.SERVICE);
155    get_record.setAttribute(OAIXML.NAME, OAIXML.GET_RECORD);
156    get_record.setAttribute(GSXML.TYPE_ATT, "oai");
157    this.short_service_info.appendChild(get_record);
158   
159    return true;
160  }
161  /** returns a specific service description */
162  public Element getServiceDescription(String service_id, String lang, String subset) {
163   
164    if (service_id.equals(OAIXML.IDENTIFY)) {
165      Element identify = this.doc.createElement(OAIXML.SERVICE);
166      identify.setAttribute(OAIXML.NAME, OAIXML.IDENTIFY);
167      identify.setAttribute(GSXML.TYPE_ATT, "oai");
168      return identify;
169    }
170    if (service_id.equals(OAIXML.LIST_RECORDS)) {
171      Element list_records = this.doc.createElement(OAIXML.SERVICE);
172      list_records.setAttribute(OAIXML.NAME, OAIXML.LIST_RECORDS);
173      list_records.setAttribute(GSXML.TYPE_ATT, "oai");
174      return list_records;
175    }
176   
177    if (service_id.equals(OAIXML.LIST_IDENTIFIERS)) {
178      Element list_identifiers = this.doc.createElement(OAIXML.SERVICE);
179      list_identifiers.setAttribute(OAIXML.NAME, OAIXML.LIST_IDENTIFIERS);
180      list_identifiers.setAttribute(GSXML.TYPE_ATT, "oai");
181      return list_identifiers;
182    }
183    if (service_id.equals(OAIXML.LIST_SETS)) {
184      Element list_sets = this.doc.createElement(OAIXML.SERVICE);
185      list_sets.setAttribute(OAIXML.NAME, OAIXML.LIST_SETS);
186      list_sets.setAttribute(GSXML.TYPE_ATT, "oai");
187      return list_sets;
188    }
189    if (service_id.equals(OAIXML.LIST_METADATA_FORMATS)) {
190      Element list_metadata_formats = this.doc.createElement(OAIXML.SERVICE);
191      list_metadata_formats.setAttribute(OAIXML.NAME, OAIXML.LIST_METADATA_FORMATS);
192      list_metadata_formats.setAttribute(GSXML.TYPE_ATT, "oai");
193      return list_metadata_formats;
194    }
195   
196    if (service_id.equals(OAIXML.GET_RECORD)) {
197      Element get_record = this.doc.createElement(OAIXML.SERVICE);
198      get_record.setAttribute(OAIXML.NAME, OAIXML.GET_RECORD);
199      get_record.setAttribute(GSXML.TYPE_ATT, "oai");
200      return get_record;
201    }
202   
203    return null;
204  }
205  /** return the metadata information about this set of the repository */
206  protected Element processIdentify(Element req) {
207    return null;
208  }
209  /** return the metadata information  */
210  protected Element processListSets(Element req) {
211    //This method is never called unless each set in the returned message contain a
212    //'description' element so that we need to ask each collection for their info
213    return null;   
214  }
215  /** return the metadata information  */
216  protected Element processGetRecord(Element req) {
217    /** arguments:
218        identifier: required
219        metadataPrefix: required
220     *  Exceptions: badArgument; cannotDisseminateFormat; idDoesNotExist
221     */
222    NodeList params = GSXML.getChildrenByTagName(req, OAIXML.PARAM);
223    HashMap param_map = OAIXML.getParamMap(params);   
224   
225    String prefix = (String)param_map.get(OAIXML.METADATA_PREFIX);
226    if (prefix == null || prefix.equals("")) {
227      //Just a double-check
228      logger.error("the value of metadataPrefix att is not present in the request.");
229      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
230    }
231   
232    Element metadata_format = getMetadataFormatElement(prefix);
233    if(metadata_format == null) {
234      logger.error("metadata prefix is not supported.");
235      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
236    }
237   
238    String oid = (String)param_map.get(OAIXML.OID);
239
240    //get a DBInfo object of the identifier; if this identifier is not present in the database,
241    // null is returned.
242    DBInfo info = this.coll_db.getInfo(oid);
243    if (info == null) {
244      logger.error("OID: " + oid + " is not present in the database.");
245      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.ID_DOES_NOT_EXIST, ""));
246    }
247
248    ArrayList keys = new ArrayList(info.getKeys());
249    String lastmodified = "";
250    if(keys.contains(OAIXML.LASTMODIFIED)) {
251      lastmodified = info.getInfo(OAIXML.LASTMODIFIED);
252    }
253    lastmodified = OAIXML.getTime(Long.parseLong(lastmodified));
254
255    Element get_record = OAIXML.createElement(OAIXML.GET_RECORD);
256    Element record = OAIXML.createElement(OAIXML.RECORD);
257    //compose the header element
258    record.appendChild(createHeaderElement(oid, lastmodified));     
259    //compose the metadata element
260    record.appendChild(createMetadataElement(prefix, info, metadata_format));
261    get_record.appendChild(record);
262    return OAIXML.getResponse(get_record);
263  }
264  /** return a list of identifiers  */
265  protected Element processListIdentifiers(Element req) {
266    /** arguments:
267        metadataPrefix: required
268     *  from: optional
269     *  until: optional
270     *  set: optional
271     *  resumptionToken: exclusive and optional (ignored as it has been handled by OAIReceptionist)
272     *  Exceptions: badArgument; cannotDisseminateFormat; idDoesNotExist
273     */
274    NodeList params = GSXML.getChildrenByTagName(req, OAIXML.PARAM);
275   
276    if(params.getLength() == 0) {
277      logger.error("must at least have the metadataPrefix parameter, can't be none");
278      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.BAD_ARGUMENT, ""));
279    }
280   
281    HashMap param_map = OAIXML.getParamMap(params); 
282   
283    String prefix = "";
284    Date from_date = null;
285    Date until_date = null;
286   
287    if(param_map.containsKey(OAIXML.METADATA_PREFIX) == false) {   
288      //Just a double-check
289      logger.error("A param element containing the metadataPrefix is not present.");
290      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
291    }
292    prefix = (String)param_map.get(OAIXML.METADATA_PREFIX);
293    if (prefix == null || prefix.equals("")) {
294      //Just a double-check
295      logger.error("the value of metadataPrefix att is not present in the request.");
296      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
297    }
298   
299    if(param_map.containsKey(OAIXML.FROM)) {
300      String from = (String)param_map.get(OAIXML.FROM);
301      from_date = OAIXML.getDate(from);
302    }   
303    if(param_map.containsKey(OAIXML.UNTIL)) {
304      String until = (String)param_map.get(OAIXML.UNTIL);
305      until_date = OAIXML.getDate(until);
306    }   
307
308    Element metadata_format = getMetadataFormatElement(prefix);
309    if(metadata_format == null) {
310      logger.error("metadata prefix is not supported.");
311      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
312    }
313    ArrayList oid_list = getChildrenIds(OAIXML.BROWSELIST);
314    if (oid_list == null) {
315      logger.error("No matched records found in collection: browselist is empty");
316      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.NO_RECORDS_MATCH, ""));
317    }
318    // all validation is done
319    Element list_identifiers = OAIXML.createElement(OAIXML.LIST_IDENTIFIERS);
320    for(int i=0; i<oid_list.size(); i++) {
321      String oid = (String)oid_list.get(i);
322      DBInfo info = this.coll_db.getInfo(oid);
323      if (info == null) {
324        logger.error("Database does not contains information about oid: " +oid);
325        continue;
326      }
327      ArrayList keys = new ArrayList(info.getKeys());
328      String lastmodified = "";
329      if(keys.contains(OAIXML.LASTMODIFIED)) {
330        lastmodified = info.getInfo(OAIXML.LASTMODIFIED);
331      }
332      lastmodified = OAIXML.getTime(Long.parseLong(lastmodified));
333     
334      Date this_date = OAIXML.getDate(lastmodified);       
335      if (from_date != null) {
336        if(this_date.before(from_date)) {
337          continue;
338        }
339      }
340      if (until_date != null) {
341        if (this_date.after(until_date)) {
342          continue;
343        }
344      }     
345      //compose the header element and append it
346      list_identifiers.appendChild(createHeaderElement(oid, lastmodified));     
347    }//end of for(int i=0; i<oid_list.size(); i++) of doing thru each record
348   
349    return OAIXML.getResponse(list_identifiers);       
350  }
351  /** return a list of records  */
352  protected Element processListRecords(Element req) {
353    /** the request sent here may contain optional 'from', 'untill', 'metadataPrefix',
354     * and 'resumptionToken' params. see doListSets() in OAIReceptionist.
355     * if the request contains 'resumptionToken' then it should have been handled by the
356     * OAIReceptionist. Therefore, the request sent here must not contain 'resumptionToken'
357     * argument but a 'metadataPrefix' param. The OAIReceptionist makes sure of this.
358     */
359    NodeList params = GSXML.getChildrenByTagName(req, OAIXML.PARAM);
360   
361    if(params.getLength() == 0) {
362      logger.error("must at least have the metadataPrefix parameter, can't be none");
363      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.BAD_ARGUMENT, ""));
364    }
365   
366    HashMap param_map = OAIXML.getParamMap(params);   
367
368    String prefix = "";
369    Date from_date = null;
370    Date until_date = null;
371   
372    if(param_map.containsKey(OAIXML.METADATA_PREFIX) == false) {   
373      //Just a double-check
374      logger.error("A param element containing the metadataPrefix is not present.");
375      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
376    }
377    prefix = (String)param_map.get(OAIXML.METADATA_PREFIX);
378    if (prefix == null || prefix.equals("")) {
379      //Just a double-check
380      logger.error("the value of metadataPrefix att is not present in the request.");
381      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
382    }
383   
384    if(param_map.containsKey(OAIXML.FROM)) {
385      String from = (String)param_map.get(OAIXML.FROM);
386      from_date = OAIXML.getDate(from);
387    }   
388    if(param_map.containsKey(OAIXML.UNTIL)) {
389      String until = (String)param_map.get(OAIXML.UNTIL);
390      until_date = OAIXML.getDate(until);
391    }   
392    Element metadata_format = getMetadataFormatElement(prefix);
393    if(metadata_format == null) {
394      logger.error("metadata prefix is not supported.");
395      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
396    }
397// Another way of doing the same job!   
398//    HashMap prefix_map = OAIXML.getChildrenMapByTagName(coll_config_xml, OAIXML.METADATA_PREFIX);
399//    if(!prefix_map.contains(prefix)) {
400//      logger.error("metadata prefix is not supported.");
401//      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
402//    }
403   
404    //get a list of identifiers (it contains a list of strings)
405    ArrayList oid_list = getChildrenIds(OAIXML.BROWSELIST);
406    if (oid_list == null) {
407      logger.error("No matched records found in collection: browselist is empty");
408      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.NO_RECORDS_MATCH, ""));
409    }
410    // all validation is done
411    Element list_records = OAIXML.createElement(OAIXML.LIST_RECORDS);
412    for(int i=0; i<oid_list.size(); i++) {
413      String oid = (String)oid_list.get(i);
414      DBInfo info = this.coll_db.getInfo(oid);
415      if (info == null) {
416        logger.error("Database does not contains information about oid: " +oid);
417        continue;
418      }
419      ArrayList keys = new ArrayList(info.getKeys());
420      String lastmodified = "";
421      if(keys.contains(OAIXML.LASTMODIFIED)) {
422        lastmodified = info.getInfo(OAIXML.LASTMODIFIED);
423      }
424      lastmodified = OAIXML.getTime(Long.parseLong(lastmodified));
425     
426      Date this_date = OAIXML.getDate(lastmodified);       
427      if (from_date != null) {
428        if(this_date.before(from_date)) {
429          continue;
430        }
431      }
432      if (until_date != null) {
433        if (this_date.after(until_date)) {
434          continue;
435        }
436      }
437     
438      Element record = OAIXML.createElement(OAIXML.RECORD);
439      list_records.appendChild(record);
440      //compose the header element
441      record.appendChild(createHeaderElement(oid, lastmodified));     
442      //compose the metadata element
443      record.appendChild(createMetadataElement(prefix, info, metadata_format));
444     
445    }//end of for(int i=0; i<oid_list.size(); i++) of doing thru each record
446   
447    return OAIXML.getResponse(list_records);   
448  }
449 
450  /** get the metadataFormat element from the collectionConfig.xml containing the specified metadata prefix.
451   *  return null if not found.
452   */
453  private Element getMetadataFormatElement(String prefix) {
454    Element oai = (Element)GSXML.getChildByTagName(this.coll_config_xml, OAIXML.OAI);
455    Element list_meta_format = (Element)GSXML.getChildByTagName(oai, OAIXML.LIST_METADATA_FORMATS);
456    Element metadata_format = GSXML.getNamedElement(list_meta_format, OAIXML.METADATA_FORMAT, OAIXML.METADATA_PREFIX, prefix);
457    return metadata_format;
458  }
459  /** create the metadata element used when processing ListRecords/GetRecord requests
460   */
461  private Element createMetadataElement(String prefix, DBInfo info, Element metadata_format) {
462        //the prefix string is in the form: oai_dc, for example.
463        String prfx_str = "";
464        //the metadata namespace used to retrieve metadata in the repository
465        //For example, if the prefix is like 'oai_ex' then we used 'ex' to get the metadata
466        //Normally we would use 'dc' to find metadata.
467        String meta_ns = "";
468        if(prefix.equals(OAIXML.OAI_DC)) {
469          if(OAIXML.oai_version.equals(OAIXML.OAI_VERSION2)) {
470            prfx_str = prefix + ":" + OAIXML.DC;
471          } else {
472            prfx_str = OAIXML.DC;//oai version 1
473          }
474          meta_ns = OAIXML.DC;
475        } else {
476          prfx_str = prefix.substring(prefix.indexOf("_") + 1);
477          meta_ns = prfx_str;
478        }
479        //create the <metadata> element
480        //OAIXML.oai_version is read from OAIConfig.xml and its default value is "2.0"
481        Element prfx_str_elem = OAIXML.getMetadataPrefixElement(prfx_str, OAIXML.oai_version);
482        String[] metadata_names = getMetadataNames(metadata_format);
483        HashMap meta_map = getInfoByNames(info, metadata_names);
484        ArrayList meta_list = new ArrayList(meta_map.entrySet());
485        for (int j=0; j<meta_list.size(); j++) {
486          Entry men = (Entry)meta_list.get(j);
487          String meta_name = (String)men.getKey();
488          String meta_value = (String)men.getValue();
489          Element e = OAIXML.createElement(meta_name);
490          GSXML.setNodeText(e, meta_value);
491          prfx_str_elem.appendChild(e);
492        }
493        Element metadata = OAIXML.createElement(OAIXML.METADATA);
494        metadata.appendChild(prfx_str_elem);
495        return metadata;
496  }
497  /** create a header element used when processing requests like ListRecords/GetRecord/ListIdentifiers
498   */
499  private Element createHeaderElement(String oid, String lastmodified) {   
500        Element header = OAIXML.createElement(OAIXML.HEADER);
501        Element identifier = OAIXML.createElement(OAIXML.IDENTIFIER);
502        GSXML.setNodeText(identifier, site_name + ":" + coll_name + ":" + oid);
503        header.appendChild(identifier);
504        Element set_spec = OAIXML.createElement(OAIXML.SET_SPEC);
505        GSXML.setNodeText(set_spec, site_name + ":" + coll_name);
506        header.appendChild(set_spec);
507        Element datestamp = OAIXML.createElement(OAIXML.DATESTAMP);
508        GSXML.setNodeText(datestamp, lastmodified);
509        header.appendChild(datestamp);
510        return header;
511  }
512  /** return the metadata information  */
513  protected Element processListMetadataFormats(Element req) {
514    // the request sent here must contain an OID. see doListMetadataFormats() in OAIReceptionist
515    Element param = GSXML.getNamedElement(req, OAIXML.PARAM, OAIXML.NAME, OAIXML.OID);
516    if (param == null) {
517      logger.error("An element containing the OID attribute not is present.");
518      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.ID_DOES_NOT_EXIST, ""));
519    }
520    String oid = param.getAttribute(OAIXML.VALUE);
521    if (oid == null || oid.equals("")) {
522      logger.error("No OID is present in the request.");
523      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.ID_DOES_NOT_EXIST, ""));
524    }
525    ArrayList oid_list = getChildrenIds(OAIXML.BROWSELIST);
526    if (oid_list == null || oid_list.contains(oid) == false) {
527      logger.error("OID: " + oid + " is not present in the database.");
528      Element e= OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.ID_DOES_NOT_EXIST, ""));
529//      logger.error((new XMLConverter()).getPrettyString (e));
530      return e;
531    }
532   
533    DBInfo info = null;   
534    info = this.coll_db.getInfo(oid);
535    if (info == null) { //just double check
536      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.OAI_SERVICE_UNAVAILABLE, ""));
537    }
538   
539    NodeList meta_list = getMetadataFormatList(this.coll_config_xml);
540    if (meta_list == null || meta_list.getLength() == 0) {
541      logger.error("No metadata format is present in collectionConfig.xml");
542      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.NO_METADATA_FORMATS, ""));
543    }
544
545    Element list_metadata_formats = OAIXML.createElement(OAIXML.LIST_METADATA_FORMATS);
546    boolean has_meta_format = false;
547   
548    for (int i=0; i<meta_list.getLength(); i++) {
549      Element metadata_format = (Element)meta_list.item(i);
550      String[] metadata_names = getMetadataNames(metadata_format);
551      if (containsMetadata(info, metadata_names) == true) {
552        has_meta_format = true;
553        Element meta_fmt = OAIXML.createElement(OAIXML.METADATA_FORMAT);
554        OAIXML.copyElement(meta_fmt, metadata_format, OAIXML.METADATA_PREFIX);
555        OAIXML.copyElement(meta_fmt, metadata_format, OAIXML.METADATA_NAMESPACE);
556        OAIXML.copyElement(meta_fmt, metadata_format, OAIXML.SCHEMA);
557        list_metadata_formats.appendChild(meta_fmt);
558      }
559    }//end of for loop
560    if (has_meta_format == false) {
561      logger.error("Specified metadata names are not contained in the database.");
562      return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.NO_METADATA_FORMATS, ""));
563    } else {
564      return OAIXML.getResponse(list_metadata_formats);
565    }
566  }
567
568  /** return the ListMetadataFormats element in collectionConfig.xml
569   *  Currently, it will only contain one metadata format: oai_dc
570   */
571  protected NodeList getMetadataFormatList(Element coll_config_xml) {
572    Element oai_elem = (Element)GSXML.getChildByTagName(coll_config_xml, OAIXML.OAI);
573    Element list_meta_formats = (Element)GSXML.getChildByTagName(oai_elem, OAIXML.LIST_METADATA_FORMATS);
574    return GSXML.getChildrenByTagName(list_meta_formats, OAIXML.METADATA_FORMAT);
575  }
576  /** @param metadata_format - the metadataFormat element in collectionConfig.xml
577   */
578  protected String[] getMetadataNames(Element metadata_format) {
579    String[] names = null;
580   
581    //read the mappingList element
582    Element mapping_list = (Element)GSXML.getChildByTagName(metadata_format, OAIXML.MAPPING_LIST);
583    if (mapping_list == null) {
584      logger.info("No metadata mappings are provided in collectionConfig.xml. Use the standard Dublin Core names.");
585      names = OAIXML.getGlobalMetadataMapping(metadata_format.getAttribute(OAIXML.METADATA_PREFIX));
586     
587      return (names != null)? names : OAIXML.getDublinCoreNames();
588    }
589    NodeList mappings = GSXML.getChildrenByTagName(mapping_list, OAIXML.MAPPING);
590    int size = mappings.getLength();
591    if (size == 0) {
592        logger.info("No metadata mappings are provided in collectionConfig.xml. \n Return standard DC names.");
593        // read the standard Dublin Core metadata names
594        return OAIXML.getDublinCoreNames();
595    }
596    names = new String[size];
597    for (int i=0; i<size; i++) {
598      names[i] = GSXML.getNodeText((Element)mappings.item(i)).trim();
599    }
600    return names;
601  }
602
603  /** returns a list of the child ids in order, null if no children */
604  protected ArrayList getChildrenIds(String node_id) {
605    DBInfo info = this.coll_db.getInfo(node_id);
606    if (info == null) {
607      return null;
608    }
609   
610    String contains = info.getInfo("contains");
611    if (contains.equals("")) {
612      return null;
613    }
614    ArrayList children = new ArrayList();
615    StringTokenizer st = new StringTokenizer(contains, ";");
616    while (st.hasMoreTokens()) {
617      String child_id = st.nextToken().replaceAll("\"", node_id);
618      children.add(child_id);
619    }
620    return children;   
621  }
622  /**method to check whether any of the 'metadata_names' is contained in the 'info'.
623   * The name may be in the form: <name>,<mapped name>, in which the mapped name is
624   * optional. The mapped name is looked up in the DBInfo; if not present, use the first
625   * name which is mendatory.
626   */
627  protected boolean containsMetadata(DBInfo info, String[] metadata_names) {
628    if (metadata_names == null) return false;
629    logger.info("checking metadata names in db.");
630    for(int i=0; i<metadata_names.length; i++) {
631      int index = metadata_names[i].indexOf(",");
632      String meta_name = (index == -1) ? metadata_names[i] :
633                              metadata_names[i].substring(index + 1);
634     
635      if(info.getInfo(meta_name).equals("") == false) {
636        return true;
637      }
638    }
639    return false;
640  } 
641    /** @param keys - contains a list of keys in string format.
642     * Here is a typical record in the collection database, 'keys' contains the values in <...>:
643     *----------------------------------------------------------------------
644[HASH01a84acb0f1aad2380493b3a]
645<doctype>doc
646<hastxt>1
647<Language>en
648<Encoding>windows_1252
649<Plugin>HTMLPlug
650<FileSize>205093
651<Source>wb34te.htm
652<hascover>1
653<dls.Organization>World Bank
654<dls.Title>Development in practice: Toward Gender Equality (wb34te)
655<dls.Language>English
656<dls.AZList>A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-Z
657<dls.Subject>Women, gender and development, women's organizations
658<dls.Keyword>achieve gender equality
659<URL>http://wb34te/wb34te.htm
660<Title>Development in practice: Toward Gender Equality
661<lastmodified>1178245194
662<assocfilepath>HASH01a8.dir
663<memberof>CL3
664<archivedir>HASH01a8.dir
665<thistype>VList
666<childtype>VList
667<contains>".1;".2;".3;".4;".5;".6;".7;".8;".9
668<docnum>349
669----------------------------------------------------------------------
670     */
671  public String[] getMetadata(DBInfo info, String names) {
672    String[] name_value = new String[2];
673    ArrayList keys = new ArrayList(info.getKeys());
674    for (int i=0; i<keys.size(); i++) {
675      String key = (String)keys.get(i);
676      String first_name = "";
677      String second_name = "";
678      int index = names.indexOf(",");
679      if(index != -1) {
680        first_name = names.substring(0, index);
681        second_name = names.substring(index + 1);
682      } else {
683        first_name = second_name = names;
684      }
685      if(key.equals(second_name)) {
686        String meta_value = info.getInfo(key);
687        name_value[0] = first_name;
688        name_value[1] = meta_value;
689        return name_value;
690      }
691    }
692    return null;
693  }
694  protected HashMap getInfoByNames(DBInfo info, String[] metadata_names) {
695    HashMap map = new HashMap();
696    boolean empty_map = true;
697   
698    for(int i=0; i<metadata_names.length; i++) {
699      String[] name_value = getMetadata(info, metadata_names[i]);
700      if(name_value != null) {
701        map.put(name_value[0], name_value[1]);
702        empty_map = false;
703      }
704    }
705    return (empty_map == true) ? null : map;
706  }
707}
708
709
Note: See TracBrowser for help on using the browser.