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

Last change on this file since 28986 was 28986, checked in by kjdon, 10 years ago

method name change

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