source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/OAIPMH.java@ 23938

Last change on this file since 23938 was 23938, checked in by ak19, 13 years ago

GS3's OAIserver passes final official oaiserver validation tests: to do with earliestDatestamp. Both the datestamp of the records (documents) returned by listRecords, listIdentifiers and getRecord, as well as the earliestDatestamp returned by an Identify request are now in sync with each other. Related code changes made to perllib to write the earliestDatestamp into GS3's buildconfig.xml (and build.cfg for GS2), and to write new fields oailastmodified and oailastmodifieddate into the collection's database for each document.

File size: 27.9 KB
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:[email protected]">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
64 /** constructor */
65 public OAIPMH() {
66
67 }
68
69 public void cleanUp() {
70 super.cleanUp();//??
71 this.coll_db.closeDatabase();
72 }
73 /** configure this service
74 info is the OAIPMH service rack from collectionConfig.xml, and
75 extra_info is buildConfig.xml */
76 public boolean configure(Element info, Element extra_info) {
77 if (!super.configure(info, extra_info)){
78 logger.info("Configuring ServiceRack.java returns false.");
79 return false;
80 }
81
82 //get the names from ServiceRack.java
83 this.site_name = this.router.getSiteName();
84 this.coll_name = this.cluster_name;
85
86 logger.info("Configuring OAIPMH...");
87
88 this.config_info = info;
89
90 // the index stem is either specified in the buildConfig.xml file (extra_info) or uses the collection name
91 Element metadata_list = (Element) GSXML.getChildByTagName(extra_info, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
92 String index_stem = "";
93 String infodb_type = "";
94 if (metadata_list != null) {
95
96 Element index_stem_elem = (Element) GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "indexStem");
97
98 if (index_stem_elem != null) {
99 index_stem = GSXML.getNodeText(index_stem_elem);
100 }
101
102 Element infodb_type_elem = (Element) GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "infodbType");
103 if (infodb_type_elem != null) {
104 infodb_type = GSXML.getNodeText(infodb_type_elem);
105 }
106
107 }
108
109 if (index_stem == null || index_stem.equals("")) {
110 index_stem = this.cluster_name;
111 }
112 if (infodb_type == null || infodb_type.equals("")) {
113 infodb_type = "gdbm"; // the default
114 }
115
116 coll_db = new SimpleCollectionDatabase(infodb_type);
117 if (!coll_db.databaseOK()) {
118 logger.error("Couldn't create the collection database of type "+infodb_type);
119 return false;
120 }
121
122 // Open database for querying
123 String coll_db_file = GSFile.collectionDatabaseFile(this.site_home, this.cluster_name, index_stem, infodb_type);
124 if (!this.coll_db.openDatabase(coll_db_file, SimpleCollectionDatabase.READ)) {
125 logger.error("Could not open collection database!");
126 return false;
127 }
128
129 // the short_service_info is used by the message router to find the method names,
130 //so we just use the doc variable in class ServiceRack to create the xml; but
131 // in each method we will use OAIXML to create the response xml
132 // set up short_service_info_ - just the name
133
134 Element identify = this.doc.createElement(OAIXML.SERVICE);
135
136 identify.setAttribute(OAIXML.NAME, OAIXML.IDENTIFY);
137 identify.setAttribute(GSXML.TYPE_ATT, "oai");
138 this.short_service_info.appendChild(identify);
139
140 Element list_records = this.doc.createElement(OAIXML.SERVICE);
141 list_records.setAttribute(OAIXML.NAME, OAIXML.LIST_RECORDS);
142 list_records.setAttribute(GSXML.TYPE_ATT, "oai");
143 this.short_service_info.appendChild(list_records);
144
145 Element list_identifiers = this.doc.createElement(OAIXML.SERVICE);
146 list_identifiers.setAttribute(OAIXML.NAME, OAIXML.LIST_IDENTIFIERS);
147 list_identifiers.setAttribute(GSXML.TYPE_ATT, "oai");
148 this.short_service_info.appendChild(list_identifiers);
149
150 Element list_sets = this.doc.createElement(OAIXML.SERVICE);
151 list_sets.setAttribute(OAIXML.NAME, OAIXML.LIST_SETS);
152 list_sets.setAttribute(GSXML.TYPE_ATT, "oai");
153 this.short_service_info.appendChild(list_sets);
154
155 Element list_metadata_formats = this.doc.createElement(OAIXML.SERVICE);
156 list_metadata_formats.setAttribute(OAIXML.NAME, OAIXML.LIST_METADATA_FORMATS);
157 list_metadata_formats.setAttribute(GSXML.TYPE_ATT, "oai");
158 this.short_service_info.appendChild(list_metadata_formats);
159
160 Element get_record = this.doc.createElement(OAIXML.SERVICE);
161 get_record.setAttribute(OAIXML.NAME, OAIXML.GET_RECORD);
162 get_record.setAttribute(GSXML.TYPE_ATT, "oai");
163 this.short_service_info.appendChild(get_record);
164
165 return true;
166 }
167 /** returns a specific service description */
168 public Element getServiceDescription(String service_id, String lang, String subset) {
169
170 if (service_id.equals(OAIXML.IDENTIFY)) {
171 Element identify = this.doc.createElement(OAIXML.SERVICE);
172 identify.setAttribute(OAIXML.NAME, OAIXML.IDENTIFY);
173 identify.setAttribute(GSXML.TYPE_ATT, "oai");
174 return identify;
175 }
176 if (service_id.equals(OAIXML.LIST_RECORDS)) {
177 Element list_records = this.doc.createElement(OAIXML.SERVICE);
178 list_records.setAttribute(OAIXML.NAME, OAIXML.LIST_RECORDS);
179 list_records.setAttribute(GSXML.TYPE_ATT, "oai");
180 return list_records;
181 }
182
183 if (service_id.equals(OAIXML.LIST_IDENTIFIERS)) {
184 Element list_identifiers = this.doc.createElement(OAIXML.SERVICE);
185 list_identifiers.setAttribute(OAIXML.NAME, OAIXML.LIST_IDENTIFIERS);
186 list_identifiers.setAttribute(GSXML.TYPE_ATT, "oai");
187 return list_identifiers;
188 }
189 if (service_id.equals(OAIXML.LIST_SETS)) {
190 Element list_sets = this.doc.createElement(OAIXML.SERVICE);
191 list_sets.setAttribute(OAIXML.NAME, OAIXML.LIST_SETS);
192 list_sets.setAttribute(GSXML.TYPE_ATT, "oai");
193 return list_sets;
194 }
195 if (service_id.equals(OAIXML.LIST_METADATA_FORMATS)) {
196 Element list_metadata_formats = this.doc.createElement(OAIXML.SERVICE);
197 list_metadata_formats.setAttribute(OAIXML.NAME, OAIXML.LIST_METADATA_FORMATS);
198 list_metadata_formats.setAttribute(GSXML.TYPE_ATT, "oai");
199 return list_metadata_formats;
200 }
201
202 if (service_id.equals(OAIXML.GET_RECORD)) {
203 Element get_record = this.doc.createElement(OAIXML.SERVICE);
204 get_record.setAttribute(OAIXML.NAME, OAIXML.GET_RECORD);
205 get_record.setAttribute(GSXML.TYPE_ATT, "oai");
206 return get_record;
207 }
208
209 return null;
210 }
211 /** return the metadata information about this set of the repository */
212 protected Element processIdentify(Element req) {
213 return null;
214 }
215 /** return the metadata information */
216 protected Element processListSets(Element req) {
217 //This method is never called unless each set in the returned message contain a
218 //'description' element so that we need to ask each collection for their info
219 return null;
220 }
221 /** return the metadata information */
222 protected Element processGetRecord(Element req) {
223 /** arguments:
224 identifier: required
225 metadataPrefix: required
226 * Exceptions: badArgument; cannotDisseminateFormat; idDoesNotExist
227 */
228 NodeList params = GSXML.getChildrenByTagName(req, OAIXML.PARAM);
229 HashMap param_map = OAIXML.getParamMap(params);
230
231 String prefix = (String)param_map.get(OAIXML.METADATA_PREFIX);
232 if (prefix == null || prefix.equals("")) {
233 //Just a double-check
234 logger.error("the value of metadataPrefix att is not present in the request.");
235 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
236 }
237
238 Element metadata_format = getMetadataFormatElement(prefix);
239 if(metadata_format == null) {
240 logger.error("metadata prefix is not supported.");
241 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
242 }
243
244 String oid = (String)param_map.get(OAIXML.OID);
245
246 //get a DBInfo object of the identifier; if this identifier is not present in the database,
247 // null is returned.
248 DBInfo info = this.coll_db.getInfo(oid);
249 if (info == null) {
250 logger.error("OID: " + oid + " is not present in the database.");
251 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.ID_DOES_NOT_EXIST, ""));
252 }
253
254 ArrayList keys = new ArrayList(info.getKeys());
255 String oailastmodified = "";
256 if(keys.contains(OAIXML.OAI_LASTMODIFIED)) {
257 oailastmodified = info.getInfo(OAIXML.OAI_LASTMODIFIED);
258 oailastmodified = OAIXML.getTime(Long.parseLong(oailastmodified)*1000); // java wants dates in milliseconds
259 }
260
261 Element get_record = OAIXML.createElement(OAIXML.GET_RECORD);
262 Element record = OAIXML.createElement(OAIXML.RECORD);
263 //compose the header element
264 record.appendChild(createHeaderElement(oid, oailastmodified));
265 //compose the metadata element
266 record.appendChild(createMetadataElement(prefix, info, metadata_format));
267 get_record.appendChild(record);
268 return OAIXML.getResponse(get_record);
269 }
270 /** return a list of identifiers */
271 protected Element processListIdentifiers(Element req) {
272 /** arguments:
273 metadataPrefix: required
274 * from: optional
275 * until: optional
276 * set: optional
277 * resumptionToken: exclusive and optional (ignored as it has been handled by OAIReceptionist)
278 * Exceptions: badArgument; cannotDisseminateFormat; idDoesNotExist
279 */
280 NodeList params = GSXML.getChildrenByTagName(req, OAIXML.PARAM);
281
282 if(params.getLength() == 0) {
283 logger.error("must at least have the metadataPrefix parameter, can't be none");
284 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.BAD_ARGUMENT, ""));
285 }
286
287 HashMap param_map = OAIXML.getParamMap(params);
288
289 String prefix = "";
290 Date from_date = null;
291 Date until_date = null;
292
293 if(param_map.containsKey(OAIXML.METADATA_PREFIX) == false) {
294 //Just a double-check
295 logger.error("A param element containing the metadataPrefix is not present.");
296 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
297 }
298 prefix = (String)param_map.get(OAIXML.METADATA_PREFIX);
299 if (prefix == null || prefix.equals("")) {
300 //Just a double-check
301 logger.error("the value of metadataPrefix att is not present in the request.");
302 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
303 }
304
305 if(param_map.containsKey(OAIXML.FROM)) {
306 String from = (String)param_map.get(OAIXML.FROM);
307 from_date = OAIXML.getDate(from);
308 }
309 if(param_map.containsKey(OAIXML.UNTIL)) {
310 String until = (String)param_map.get(OAIXML.UNTIL);
311 until_date = OAIXML.getDate(until);
312 }
313
314 Element metadata_format = getMetadataFormatElement(prefix);
315 if(metadata_format == null) {
316 logger.error("metadata prefix is not supported.");
317 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
318 }
319 ArrayList oid_list = getChildrenIds(OAIXML.BROWSELIST);
320 if (oid_list == null) {
321 logger.error("No matched records found in collection: browselist is empty");
322 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.NO_RECORDS_MATCH, ""));
323 }
324 // all validation is done
325 Element list_identifiers = OAIXML.createElement(OAIXML.LIST_IDENTIFIERS);
326 for(int i=0; i<oid_list.size(); i++) {
327 String oid = (String)oid_list.get(i);
328 DBInfo info = this.coll_db.getInfo(oid);
329 if (info == null) {
330 logger.error("Database does not contains information about oid: " +oid);
331 continue;
332 }
333 ArrayList keys = new ArrayList(info.getKeys());
334 String oailastmodified = "";
335 if(keys.contains(OAIXML.OAI_LASTMODIFIED)) {
336 oailastmodified = info.getInfo(OAIXML.OAI_LASTMODIFIED);
337 oailastmodified = OAIXML.getTime(Long.parseLong(oailastmodified)*1000); // java wants dates in milliseconds
338 }
339
340 Date this_date = OAIXML.getDate(oailastmodified);
341 if (from_date != null) {
342 if(this_date.before(from_date)) {
343 continue;
344 }
345 }
346 if (until_date != null) {
347 if (this_date.after(until_date)) {
348 continue;
349 }
350 }
351 //compose the header element and append it
352 list_identifiers.appendChild(createHeaderElement(oid, oailastmodified));
353 }//end of for(int i=0; i<oid_list.size(); i++) of doing thru each record
354
355 return OAIXML.getResponse(list_identifiers);
356 }
357 /** return a list of records */
358 protected Element processListRecords(Element req) {
359 /** the request sent here may contain optional 'from', 'untill', 'metadataPrefix',
360 * and 'resumptionToken' params. see doListSets() in OAIReceptionist.
361 * if the request contains 'resumptionToken' then it should have been handled by the
362 * OAIReceptionist. Therefore, the request sent here must not contain 'resumptionToken'
363 * argument but a 'metadataPrefix' param. The OAIReceptionist makes sure of this.
364 */
365 NodeList params = GSXML.getChildrenByTagName(req, OAIXML.PARAM);
366
367 if(params.getLength() == 0) {
368 logger.error("must at least have the metadataPrefix parameter, can't be none");
369 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.BAD_ARGUMENT, ""));
370 }
371
372 HashMap param_map = OAIXML.getParamMap(params);
373
374 String prefix = "";
375 Date from_date = null;
376 Date until_date = null;
377
378 if(param_map.containsKey(OAIXML.METADATA_PREFIX) == false) {
379 //Just a double-check
380 logger.error("A param element containing the metadataPrefix is not present.");
381 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
382 }
383 prefix = (String)param_map.get(OAIXML.METADATA_PREFIX);
384 if (prefix == null || prefix.equals("")) {
385 //Just a double-check
386 logger.error("the value of metadataPrefix att is not present in the request.");
387 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.CANNOT_DISSEMINATE_FORMAT, ""));
388 }
389
390 if(param_map.containsKey(OAIXML.FROM)) {
391 String from = (String)param_map.get(OAIXML.FROM);
392 from_date = OAIXML.getDate(from);
393 }
394 if(param_map.containsKey(OAIXML.UNTIL)) {
395 String until = (String)param_map.get(OAIXML.UNTIL);
396 until_date = OAIXML.getDate(until);
397 }
398 Element metadata_format = getMetadataFormatElement(prefix);
399 if(metadata_format == null) {
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 oailastmodified = "";
421 if(keys.contains(OAIXML.OAI_LASTMODIFIED)) {
422 oailastmodified = info.getInfo(OAIXML.OAI_LASTMODIFIED);
423 oailastmodified = OAIXML.getTime(Long.parseLong(oailastmodified)*1000); // java wants dates in milliseconds
424 }
425
426 Date this_date = OAIXML.getDate(oailastmodified);
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, oailastmodified));
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 list_meta_format = (Element)GSXML.getChildByTagName(this.config_info, OAIXML.LIST_METADATA_FORMATS);
455 Element metadata_format = GSXML.getNamedElement(list_meta_format, OAIXML.METADATA_FORMAT, OAIXML.METADATA_PREFIX, prefix);
456 return metadata_format;
457 }
458 /** create the metadata element used when processing ListRecords/GetRecord requests
459 */
460 private Element createMetadataElement(String prefix, DBInfo info, Element metadata_format) {
461 //the prefix string is in the form: oai_dc, for example.
462 String prfx_str = "";
463 //the metadata namespace used to retrieve metadata in the repository
464 //For example, if the prefix is like 'oai_ex' then we used 'ex' to get the metadata
465 //Normally we would use 'dc' to find metadata.
466 String meta_ns = "";
467 if(prefix.equals(OAIXML.OAI_DC)) {
468 if(OAIXML.oai_version.equals(OAIXML.OAI_VERSION2)) {
469 prfx_str = prefix + ":" + OAIXML.DC;
470 } else {
471 prfx_str = OAIXML.DC;//oai version 1
472 }
473 meta_ns = OAIXML.DC;
474 } else {
475 prfx_str = prefix.substring(prefix.indexOf("_") + 1);
476 meta_ns = prfx_str;
477 }
478 //create the <metadata> element
479 //OAIXML.oai_version is read from OAIConfig.xml and its default value is "2.0"
480 Element metadata = OAIXML.createElement(OAIXML.METADATA);
481 Element prfx_str_elem = OAIXML.getMetadataPrefixElement(prfx_str, OAIXML.oai_version);
482 metadata.appendChild(prfx_str_elem);
483 String[] metadata_names = getMetadataNameMapping(metadata_format);
484 HashMap meta_map = getInfoByNames(info, metadata_names);
485 if (meta_map == null) {
486 return metadata;
487 }
488 ArrayList meta_list = new ArrayList(meta_map.entrySet());
489 for (int j=0; j<meta_list.size(); j++) {
490 Entry men = (Entry)meta_list.get(j);
491 String meta_name = (String)men.getKey();
492 //meta_name = meta_name.replace('.', ':'); // namespace separator should be : for oai
493 String meta_value = (String)men.getValue();
494 Element e = OAIXML.createElement(meta_name);
495 GSXML.setNodeText(e, meta_value);
496 prfx_str_elem.appendChild(e);
497 }
498
499 return metadata;
500 }
501 /** create a header element used when processing requests like ListRecords/GetRecord/ListIdentifiers
502 */
503 private Element createHeaderElement(String oid, String oailastmodified) {
504 Element header = OAIXML.createElement(OAIXML.HEADER);
505 Element identifier = OAIXML.createElement(OAIXML.IDENTIFIER);
506 GSXML.setNodeText(identifier, site_name + ":" + coll_name + ":" + oid);
507 header.appendChild(identifier);
508 Element set_spec = OAIXML.createElement(OAIXML.SET_SPEC);
509 GSXML.setNodeText(set_spec, site_name + ":" + coll_name);
510 header.appendChild(set_spec);
511 Element datestamp = OAIXML.createElement(OAIXML.DATESTAMP);
512 GSXML.setNodeText(datestamp, oailastmodified);
513 header.appendChild(datestamp);
514 return header;
515 }
516 /** return the metadata information */
517 protected Element processListMetadataFormats(Element req) {
518 // the request sent here must contain an OID. see doListMetadataFormats() in OAIReceptionist
519 Element param = GSXML.getNamedElement(req, OAIXML.PARAM, OAIXML.NAME, OAIXML.OID);
520 if (param == null) {
521 logger.error("An element containing the OID attribute not is present.");
522 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.ID_DOES_NOT_EXIST, ""));
523 }
524 String oid = param.getAttribute(OAIXML.VALUE);
525 if (oid == null || oid.equals("")) {
526 logger.error("No OID is present in the request.");
527 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.ID_DOES_NOT_EXIST, ""));
528 }
529 ArrayList oid_list = getChildrenIds(OAIXML.BROWSELIST);
530 if (oid_list == null || oid_list.contains(oid) == false) {
531 logger.error("OID: " + oid + " is not present in the database.");
532 Element e= OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.ID_DOES_NOT_EXIST, ""));
533// logger.error((new XMLConverter()).getPrettyString (e));
534 return e;
535 }
536
537 DBInfo info = null;
538 info = this.coll_db.getInfo(oid);
539 if (info == null) { //just double check
540 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.OAI_SERVICE_UNAVAILABLE, ""));
541 }
542
543 NodeList meta_list = getMetadataFormatList();
544 if (meta_list == null || meta_list.getLength() == 0) {
545 logger.error("No metadata format is present in collectionConfig.xml");
546 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.NO_METADATA_FORMATS, ""));
547 }
548
549 Element list_metadata_formats = OAIXML.createElement(OAIXML.LIST_METADATA_FORMATS);
550 boolean has_meta_format = false;
551
552 for (int i=0; i<meta_list.getLength(); i++) {
553 Element metadata_format = (Element)meta_list.item(i);
554 String[] metadata_names = getMetadataNameMapping(metadata_format);
555 if (containsMetadata(info, metadata_names) == true) {
556 has_meta_format = true;
557 Element meta_fmt = OAIXML.createElement(OAIXML.METADATA_FORMAT);
558 OAIXML.copyElement(meta_fmt, metadata_format, OAIXML.METADATA_PREFIX);
559 OAIXML.copyElement(meta_fmt, metadata_format, OAIXML.METADATA_NAMESPACE);
560 OAIXML.copyElement(meta_fmt, metadata_format, OAIXML.SCHEMA);
561 list_metadata_formats.appendChild(meta_fmt);
562 }
563 }//end of for loop
564 if (has_meta_format == false) {
565 logger.error("Specified metadata names are not contained in the database.");
566 return OAIXML.getResponse(OAIXML.createErrorElement(OAIXML.NO_METADATA_FORMATS, ""));
567 } else {
568 return OAIXML.getResponse(list_metadata_formats);
569 }
570 }
571
572 /** return the ListMetadataFormats element in collectionConfig.xml
573 * Currently, it will only contain one metadata format: oai_dc
574 */
575 protected NodeList getMetadataFormatList() {
576 Element list_meta_formats = (Element)GSXML.getChildByTagName(this.config_info, OAIXML.LIST_METADATA_FORMATS);
577 return GSXML.getChildrenByTagName(list_meta_formats, OAIXML.METADATA_FORMAT);
578 }
579 /** @param metadata_format - the metadataFormat element in collectionConfig.xml
580 */
581 protected String[] getMetadataNameMapping(Element metadata_format) {
582
583 String[] names = OAIXML.getMetadataMapping(metadata_format);
584 if (names != null) {
585 return names;
586 }
587 logger.info("No metadata mappings are provided in collectionConfig.xml. Try for global mapping");
588 names = OAIXML.getGlobalMetadataMapping(metadata_format.getAttribute(OAIXML.METADATA_PREFIX));
589 return names;
590 }
591
592 /** returns a list of the child ids in order, null if no children */
593 protected ArrayList getChildrenIds(String node_id) {
594 DBInfo info = this.coll_db.getInfo(node_id);
595 if (info == null) {
596 return null;
597 }
598
599 String contains = info.getInfo("contains");
600 if (contains.equals("")) {
601 return null;
602 }
603 ArrayList children = new ArrayList();
604 StringTokenizer st = new StringTokenizer(contains, ";");
605 while (st.hasMoreTokens()) {
606 String child_id = st.nextToken().replaceAll("\"", node_id);
607 children.add(child_id);
608 }
609 return children;
610 }
611 /**method to check whether any of the 'metadata_names' is contained in the 'info'.
612 * The name may be in the form: <name>,<mapped name>, in which the mapped name is
613 * optional. The mapped name is looked up in the DBInfo; if not present, use the first
614 * name which is mendatory.
615 */
616 protected boolean containsMetadata(DBInfo info, String[] metadata_names) {
617 if (metadata_names == null) return false;
618 logger.info("checking metadata names in db.");
619 for(int i=0; i<metadata_names.length; i++) {
620 int index = metadata_names[i].indexOf(",");
621 String meta_name = (index == -1) ? metadata_names[i] :
622 metadata_names[i].substring(index + 1);
623
624 if(info.getInfo(meta_name).equals("") == false) {
625 return true;
626 }
627 }
628 return false;
629 }
630 /** @param keys - contains a list of keys in string format.
631 * Here is a typical record in the collection database, 'keys' contains the values in <...>:
632 *----------------------------------------------------------------------
633[HASH01a84acb0f1aad2380493b3a]
634<doctype>doc
635<hastxt>1
636<Language>en
637<Encoding>windows_1252
638<Plugin>HTMLPlug
639<FileSize>205093
640<Source>wb34te.htm
641<hascover>1
642<dls.Organization>World Bank
643<dls.Title>Development in practice: Toward Gender Equality (wb34te)
644<dls.Language>English
645<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
646<dls.Subject>Women, gender and development, women's organizations
647<dls.Keyword>achieve gender equality
648<URL>http://wb34te/wb34te.htm
649<Title>Development in practice: Toward Gender Equality
650<lastmodified>1178245194
651<assocfilepath>HASH01a8.dir
652<memberof>CL3
653<archivedir>HASH01a8.dir
654<thistype>VList
655<childtype>VList
656<contains>".1;".2;".3;".4;".5;".6;".7;".8;".9
657<docnum>349
658<oailastmodified>1303283795
659<lastmodifieddate>20110412
660<oailastmodifieddate>20110420
661----------------------------------------------------------------------
662 */
663 public String[] getMetadata(DBInfo info, String names) {
664 String[] name_value = new String[2];
665 ArrayList keys = new ArrayList(info.getKeys());
666 for (int i=0; i<keys.size(); i++) {
667 String key = (String)keys.get(i);
668 String first_name = "";
669 String second_name = "";
670 int index = names.indexOf(",");
671 if(index != -1) {
672 first_name = names.substring(0, index);
673 second_name = names.substring(index + 1);
674 } else {
675 first_name = second_name = names;
676 }
677 if(key.equals(second_name)) {
678 String meta_value = info.getInfo(key);
679 name_value[0] = first_name;
680 name_value[1] = meta_value;
681 return name_value;
682 }
683 }
684 return null;
685 }
686 protected HashMap getInfoByNames(DBInfo info, String[] metadata_names) {
687
688 if (metadata_names == null) {
689 return null;
690 }
691 HashMap map = new HashMap();
692 boolean empty_map = true;
693
694 for(int i=0; i<metadata_names.length; i++) {
695 String[] name_value = getMetadata(info, metadata_names[i]);
696 if(name_value != null) {
697 map.put(name_value[0], name_value[1]);
698 empty_map = false;
699 }
700 }
701 return (empty_map == true) ? null : map;
702 }
703}
704
705
Note: See TracBrowser for help on using the repository browser.