source: trunk/gsdl3/src/java/org/greenstone/gsdl3/action/DocumentAction.java@ 4036

Last change on this file since 4036 was 4036, checked in by kjdon, 21 years ago

the service list got from MR may have services from a remote site - you need to use the service name that was supplied by the MR description, rather than the one that comes back in the service description - eventually we may get rid of the service element in the descripiton response

  • Property svn:keywords set to Author Date Id Revision
File size: 16.6 KB
Line 
1/*
2 * DocumentAction.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.action;
20
21// Greenstone classes
22import org.greenstone.gsdl3.core.ModuleInterface;
23import org.greenstone.gsdl3.util.*;
24
25// XML classes
26import org.w3c.dom.Document;
27import org.w3c.dom.Element;
28import org.w3c.dom.Node;
29import org.w3c.dom.NodeList;
30
31// General Java classes
32import java.util.HashMap;
33import java.io.File;
34
35
36/** Action class for retrieving Documents via the message router
37 */
38public class DocumentAction extends Action {
39
40 // this is used to specify that the sibling nodes of a selected one should be obtained
41 public static final String SIBLING_ARG = "sib";
42
43 /** if this is set to true, when a document is displayed, any annotation
44 * type services (enrich) will be offered to the user as well */
45 protected static final boolean provide_annotations = true;
46
47 /* add the action specific args to the cgi param list
48 */
49 public void addCGIParams() {
50 cgi_.addStaticParam(SIBLING_ARG);
51 }
52
53
54 public Element process (Element message)
55 {
56 // for now, no subaction eventually we may want to have subactions such as text assoc or something ?
57
58 // check that the stylesheet is present
59 String stylesheet = GSFile.stylesheetFile(config_, "document.xsl");
60 if (stylesheet == null) {
61 System.err.println("DocumentAction Error: document stylesheet not found!");
62 return null;
63 }
64
65 // get the request - assume only one
66 Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
67 Element cgi_paramList = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
68 HashMap params = GSXML.extractParams(cgi_paramList, false);
69
70 String collection = (String) params.get(GSCGI.COLLECTION_ARG);
71 String lang = request.getAttribute(GSXML.LANG_ATT);
72 String document_name = (String) params.get(GSCGI.DOCUMENT_ARG);
73 if (document_name == null || document_name.equals("")) {
74 System.err.println("DocumentAction Error: no document specified!");
75 return null;
76 }
77
78 //whether to retrieve siblings or not
79 boolean get_siblings = false;
80 String sibs = (String) params.get(SIBLING_ARG);
81 if (sibs != null && sibs.equals("1")) {
82 get_siblings = true;
83 }
84
85 // Create the return page tree
86 Element page = doc_.createElement(GSXML.PAGE_ELEM);
87 page.setAttribute(GSXML.LANG_ATT, lang);
88
89 // Add the display element, config stuff, and original request from the message
90 page.appendChild(doc_.importNode(GSXML.getChildByTagName(message, GSXML.DISPLAY_ELEM), true));
91 page.appendChild(doc_.importNode(GSXML.getChildByTagName(message, GSXML.CONFIGURATION_ELEM), true));
92 Element page_request = GSXML.duplicateWithNewName(doc_, request, GSXML.PAGE_REQUEST_ELEM, true);
93 page.appendChild(page_request);
94 // the element for all the response data
95 Element page_response = doc_.createElement(GSXML.PAGE_RESPONSE_ELEM);
96 page.appendChild(page_response);
97
98 // get the additional data needed for the page
99 getBackgroundData(page_response, collection, lang);
100
101 // the_document is where all the doc info - structure and metadata etc
102 //- is added into, to be returned in the page
103 Element the_document = doc_.createElement(GSXML.DOCUMENT_ELEM);
104 page_response.appendChild(the_document);
105
106
107 // Build a request to obtain the document structure
108 Element ds_message = doc_.createElement(GSXML.MESSAGE_ELEM);
109 String to = GSPath.appendLink(collection, "DocumentStructureRetrieve"); // Hard-wired?
110 Element ds_request = GSXML.createBasicRequest(doc_,GSXML.REQUEST_TYPE_PROCESS, to, lang);
111 ds_message.appendChild(ds_request);
112
113 // Create a parameter list to specify the required structure information
114 Element ds_param_list = doc_.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
115 ds_request.appendChild(ds_param_list);
116 Element ds_param = doc_.createElement(GSXML.PARAM_ELEM);
117 ds_param_list.appendChild(ds_param);
118 ds_param.setAttribute(GSXML.NAME_ATT, "structure");
119 ds_param.setAttribute(GSXML.VALUE_ATT, "ancestors");
120 ds_param = doc_.createElement(GSXML.PARAM_ELEM);
121 ds_param_list.appendChild(ds_param);
122 ds_param.setAttribute(GSXML.NAME_ATT, "structure");
123 ds_param.setAttribute(GSXML.VALUE_ATT, "children");
124 if (get_siblings) {
125 ds_param = doc_.createElement(GSXML.PARAM_ELEM);
126 ds_param_list.appendChild(ds_param);
127 ds_param.setAttribute(GSXML.NAME_ATT, "structure");
128 ds_param.setAttribute(GSXML.VALUE_ATT, "siblings");
129 }
130 // create a doc_node_list and put in the doc_node that we are interested in
131 Element ds_doc_list = doc_.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
132 ds_request.appendChild(ds_doc_list);
133 Element ds_doc = doc_.createElement(GSXML.DOC_NODE_ELEM);
134 ds_doc_list.appendChild(ds_doc);
135 ds_doc.setAttribute(GSXML.NODE_ID_ATT, document_name);
136
137 // Process the document structure retrieve message
138 // System.out.println("(DocumentAction) Structure request:\n" + converter_.getString(ds_message));
139 Element ds_response_message = (Element) mr_.process(ds_message);
140 // System.out.println("(DocumentAction) Structure response:\n" + converter_.getString(ds_response_message));
141
142 // get the doc_node bit
143 String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
144 path = GSPath.appendLink(path, GSXML.DOC_NODE_ELEM);
145 path = GSPath.appendLink(path, GSXML.NODE_STRUCTURE_ELEM);
146 Element ds_response_structure = (Element) GSXML.getNodeByPath(ds_response_message, path);
147
148 // add the contents of the structure bit into the_document
149 NodeList structs = ds_response_structure.getChildNodes();
150 for (int i=0; i<structs.getLength();i++) {
151 the_document.appendChild(doc_.importNode(structs.item(i), true));
152 }
153
154 // Build a request to obtain some document metadata
155 Element dm_message = doc_.createElement(GSXML.MESSAGE_ELEM);
156 to = GSPath.appendLink(collection, "DocumentMetadataRetrieve"); // Hard-wired?
157 Element dm_request = GSXML.createBasicRequest(doc_, GSXML.REQUEST_TYPE_PROCESS, to, lang);
158 dm_message.appendChild(dm_request);
159 // Create a parameter list to specify the required metadata information
160 // for now get Title
161 Element dm_param_list = doc_.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
162 dm_request.appendChild(dm_param_list);
163 Element dm_param = doc_.createElement(GSXML.PARAM_ELEM);
164 dm_param_list.appendChild(dm_param);
165 dm_param.setAttribute(GSXML.NAME_ATT, "metadata");
166 dm_param.setAttribute(GSXML.VALUE_ATT, "Title");
167
168 // create the doc node list for the metadata request
169 Element dm_doc_list = doc_.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
170 dm_request.appendChild(dm_doc_list);
171
172 // Add each node from the structure response into the metadata request
173 NodeList doc_nodes = the_document.getElementsByTagName(GSXML.DOC_NODE_ELEM);
174 for (int i = 0; i < doc_nodes.getLength(); i++) {
175 Element doc_node = (Element) doc_nodes.item(i);
176 String doc_node_id = doc_node.getAttribute(GSXML.NODE_ID_ATT);
177
178 // Add the documentNode to the list
179 Element dm_doc_node = doc_.createElement(GSXML.DOC_NODE_ELEM);
180 dm_doc_list.appendChild(dm_doc_node);
181 dm_doc_node.setAttribute(GSXML.NODE_ID_ATT, doc_node_id);
182 dm_doc_node.setAttribute(GSXML.NODE_TYPE_ATT,
183 doc_node.getAttribute(GSXML.NODE_TYPE_ATT));
184 }
185
186 // we also want a metadata request to the top level document to get
187 // assocfilepath - this could be cached too
188 Element doc_meta_request = GSXML.createBasicRequest(doc_, GSXML.REQUEST_TYPE_PROCESS, to, lang);
189 dm_message.appendChild(doc_meta_request);
190 Element doc_meta_param_list = doc_.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
191 doc_meta_request.appendChild(doc_meta_param_list);
192 Element doc_param = doc_.createElement(GSXML.PARAM_ELEM);
193 doc_meta_param_list.appendChild(doc_param);
194 doc_param.setAttribute(GSXML.NAME_ATT, "metadata");
195 doc_param.setAttribute(GSXML.VALUE_ATT, "assocfilepath");
196
197 // create the doc node list for the metadata request
198 Element doc_list = doc_.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
199 doc_meta_request.appendChild(doc_list);
200
201 Element doc_node = doc_.createElement(GSXML.DOC_NODE_ELEM);
202 // teh node we want is the root document node
203 doc_node.setAttribute(GSXML.NODE_ID_ATT, document_name+".rt");
204 doc_list.appendChild(doc_node);
205 // System.out.println("(DocumentAction) Metadata request:\n" + converter_.getString(dm_request));
206 Element dm_response_message = (Element) mr_.process(dm_message);
207 // System.out.println("(DocumentAction) Metadata response:\n" + converter_.getString(dm_response));
208
209 path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
210 Element dm_response_doc_list = (Element) GSXML.getNodeByPath(dm_response_message, path);
211
212 // Merge the metadata with the structure information
213 NodeList dm_response_docs = dm_response_doc_list.getChildNodes();
214 for (int i = 0; i < doc_nodes.getLength(); i++) {
215 GSXML.mergeMetadataLists(doc_nodes.item(i), dm_response_docs.item(i));
216 }
217 // get teh top level do metadata out
218 Element doc_meta_response = (Element)dm_response_message.getElementsByTagName(GSXML.RESPONSE_ELEM).item(1);
219 Element doc_meta_list = (Element)GSXML.getNodeByPath(doc_meta_response, "documentNodeList/documentNode/metadataList");
220 the_document.appendChild(doc_.importNode(doc_meta_list, true));
221
222 // Build a request to obtain some document content
223 Element dc_message = doc_.createElement(GSXML.MESSAGE_ELEM);
224 to = GSPath.appendLink(collection, "DocumentContentRetrieve"); // Hard-wired?
225 Element dc_request = GSXML.createBasicRequest(doc_, GSXML.REQUEST_TYPE_PROCESS, to, lang);
226 dc_message.appendChild(dc_request);
227
228
229 // Create a parameter list to specify the request parameters - empty for now
230 Element dc_param_list = doc_.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
231 dc_request.appendChild(dc_param_list);
232
233 // the doc list for the content request is the same as the one for the structure request
234 dc_request.appendChild(ds_doc_list);
235
236 Element dc_response_message = (Element) mr_.process(dc_message);
237
238 path = GSPath.appendLink(path, GSXML.DOC_NODE_ELEM);
239 Element dc_response_doc = (Element) GSXML.getNodeByPath(dc_response_message, path);
240 Element dc_response_doc_content = (Element) GSXML.getChildByTagName(dc_response_doc, GSXML.NODE_CONTENT_ELEM);
241 if (provide_annotations) {
242 // now we can modifiy the response doc if needed
243 String enrich_service = (String)params.get(GSCGI.SERVICE_ARG);
244 if (enrich_service != null && !enrich_service.equals("")) {
245 // send a message to the service
246 Element enrich_message = doc_.createElement(GSXML.MESSAGE_ELEM);
247 Element enrich_request = GSXML.createBasicRequest(doc_, GSXML.REQUEST_TYPE_PROCESS, enrich_service, lang);
248 enrich_message.appendChild(enrich_request);
249 Element enrich_pl = getServiceParamList(cgi_paramList);
250 enrich_request.appendChild(enrich_pl);
251 Element e_doc_list = doc_.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
252 enrich_request.appendChild(e_doc_list);
253 e_doc_list.appendChild(doc_.importNode(dc_response_doc, true));
254
255 Element enrich_response = mr_.process(enrich_message);
256
257 String [] links = {GSXML.RESPONSE_ELEM, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.DOC_NODE_ELEM, GSXML.NODE_CONTENT_ELEM};
258 path = GSPath.createPath(links);
259 dc_response_doc_content = (Element)GSXML.getNodeByPath(enrich_response, path);
260 }
261 }
262 // use the returned id rather than the sent one cos there may have
263 // been modifiers such as .pr that are removed.
264 String modified_doc_id = dc_response_doc.getAttribute(GSXML.NODE_ID_ATT);
265 the_document.setAttribute("selectedNode", modified_doc_id);
266 // Merge the document content with the metadata and structure information
267 for (int i = 0; i < doc_nodes.getLength(); i++) {
268 Node dn = doc_nodes.item(i);
269 String dn_id = ((Element)dn).getAttribute(GSXML.NODE_ID_ATT);
270 if (dn_id.equals(modified_doc_id)) {
271 dn.appendChild(doc_.importNode(dc_response_doc_content, true));
272 break;
273 }
274 }
275
276
277 Document style_doc = converter_.getDOM(new File(stylesheet));
278 GSXSLT.absoluteIncludePaths(style_doc, config_);
279 return (Element) transformer_.transform(style_doc, page);
280 }
281
282 protected Element getServiceParamList(Element cgi_param_list) {
283
284 Element new_param_list = doc_.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
285 Element param;
286 NodeList cgi_params = cgi_param_list.getChildNodes();
287 for (int i=0; i<cgi_params.getLength(); i++) {
288 Element p = (Element) cgi_params.item(i);
289 String name = p.getAttribute(GSXML.NAME_ATT);
290 if (name.equals(GSCGI.SERVICE_ARG) || name.equals(GSCGI.REQUEST_TYPE_ARG) || name.equals(GSCGI.CLUSTER_ARG) || name.equals(GSCGI.DOCUMENT_ARG) || name.equals(SIBLING_ARG) ) {
291 continue;
292 }
293 // esle add it in to the list
294 new_param_list.appendChild(doc_.importNode(p, true));
295 }
296 return new_param_list;
297 }
298
299 /** this method gets the collection description, the format info, the
300 * list of enrich services, etc - stuff that is needed for the page,
301 * but is the same whatever the query is - should be cached */
302 protected boolean getBackgroundData(Element page_response,
303 String collection, String lang) {
304
305 // create a message to process - contains requests for the collection
306 // description, the format element, the enrich services on offer
307 // these could all be cached
308 Element info_message = doc_.createElement(GSXML.MESSAGE_ELEM);
309
310 // the collection request
311 Element coll_about_request = GSXML.createBasicRequest(doc_, GSXML.REQUEST_TYPE_DESCRIBE, collection, lang);
312 info_message.appendChild(coll_about_request);
313
314 // the format request - ignore for now, where does this request go to??
315 //Element format_request = GSXML.createBasicRequest(doc_, GSXML.REQUEST_TYPE_FORMAT, ???, lang);
316 //info_message.appendChild(format_request);
317
318 // the enrich_services request - only do this if provide_annotations is true
319
320 if (provide_annotations) {
321 Element enrich_services_request = GSXML.createBasicRequest(doc_, GSXML.REQUEST_TYPE_DESCRIBE, "", lang);
322 enrich_services_request.setAttribute(GSXML.INFO_ATT, "serviceList");
323 info_message.appendChild(enrich_services_request);
324 }
325
326 Element info_response = (Element)mr_.process(info_message);
327
328 // the collection is the first response
329 NodeList responses = info_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
330 Element coll_resp = (Element)responses.item(0);
331 page_response.appendChild(doc_.importNode(GSXML.getChildByTagName(coll_resp, GSXML.COLLECTION_ELEM), true));
332
333 //Element format_resp = (Element) responses.item(1);
334 //page_reponse.appendChild(doc_.importNode(GSXML.getChildByTagName(format_resp, GSXML.FORMAT_ELEM), true));
335
336
337 if (provide_annotations) {
338 Element services_resp = (Element)responses.item(1); // change when format request added in
339
340 // a new message for the mr
341 Element enrich_message = doc_.createElement(GSXML.MESSAGE_ELEM);
342
343 NodeList e_services = services_resp.getElementsByTagName(GSXML.SERVICE_ELEM);
344 boolean service_found = false;
345 for (int j=0; j<e_services.getLength(); j++) {
346 if (((Element)e_services.item(j)).getAttribute(GSXML.TYPE_ATT).equals("enrich")) {
347 Element s = GSXML.createBasicRequest(doc_, GSXML.REQUEST_TYPE_DESCRIBE, ((Element)e_services.item(j)).getAttribute(GSXML.NAME_ATT), lang);
348 enrich_message.appendChild(s);
349 service_found = true;
350 }
351 }
352 if (service_found) {
353 Element enrich_response = mr_.process(enrich_message);
354
355 NodeList e_responses = enrich_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
356 Element service_list = doc_.createElement(GSXML.SERVICE_ELEM + GSXML.LIST_MODIFIER);
357 for (int i=0; i<e_responses.getLength(); i++) {
358 Element e_resp = (Element)e_responses.item(i);
359 Element e_service = (Element)doc_.importNode(GSXML.getChildByTagName(e_resp, GSXML.SERVICE_ELEM), true);
360 e_service.setAttribute(GSXML.NAME_ATT, e_resp.getAttribute(GSXML.FROM_ATT));
361 Element pl = (Element)GSXML.getChildByTagName(e_service, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
362 if (pl != null) {
363 // add short names to the params in the param list
364 cgi_.paramListAddShortNames(pl);
365 }
366 service_list.appendChild(e_service);
367 }
368 page_response.appendChild(service_list);
369 }
370 } // if provide_annotations
371 return true;
372
373 }
374}
Note: See TracBrowser for help on using the repository browser.