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

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

simplified actions, the receptionist does a lot more of teh work now. actions have no knowledge of transformations, whether they are in a cgi context, and only get the info that they need - eg the collection info which is needed by the xslt is now gathered by the receptionist

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