source: greenstone3/trunk/src/java/org/greenstone/gsdl3/action/GS2BrowseAction.java@ 16688

Last change on this file since 16688 was 16688, checked in by davidb, 16 years ago

Changed 'Element process(Element)' in ModuleInterface to 'Node process(Node)'. After some deliberation is was decided this is a more useful (generic) layer of the DOM to pass information around in. Helps with the DocType problem when producing XSL Transformed pages, for example. When this was an Element, it would loose track of its DocType. Supporting method provided in XMLConverter 'Element nodeToElement(Node)' which checks a nodes docType and casts to Element if appropriate, or if a Document, typecasts to that and then extracts the top-level Element. With this fundamental change in ModuleInterface, around 20 files needed to be updated (Actions, Services, etc) that build on top of 'process()' to reflect this change, and use nodeToElement where necessary.

  • Property svn:keywords set to Author Date Id Revision
File size: 13.8 KB
Line 
1package org.greenstone.gsdl3.action;
2
3import org.greenstone.gsdl3.core.ModuleInterface;
4import org.greenstone.gsdl3.util.*;
5// XML classes
6import org.w3c.dom.Node;
7import org.w3c.dom.NodeList;
8import org.w3c.dom.Document;
9import org.w3c.dom.Element;
10
11import java.util.HashMap;
12import java.util.HashSet;
13import java.util.Vector;
14import java.io.File;
15
16import org.apache.log4j.*;
17
18/** action for GS2 style classifier browsing */
19public class GS2BrowseAction extends Action {
20
21 public static final String CLASSIFIER_ARG = "cl";
22
23 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.action.GS2BrowseAction.class.getName());
24
25 /** process the request */
26 public Node process (Node message_node) {
27
28 Element message = this.converter.nodeToElement(message_node);
29
30 // get the request - assume only one
31 Element request = (Element)GSXML.getChildByTagName(message, GSXML.REQUEST_ELEM);
32
33 // the result
34 Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
35 Element response = classifierBrowse(request);
36 result.appendChild(response);
37 return result;
38 }
39
40
41 protected Element classifierBrowse(Element request) {
42
43 Element page_response = this.doc.createElement(GSXML.RESPONSE_ELEM);
44
45 // extract the params from the cgi-request, and check that we have a coll specified
46 Element cgi_paramList = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
47 HashMap params = GSXML.extractParams(cgi_paramList, false);
48
49 String service_name = (String)params.get(GSParams.SERVICE);
50 String collection = (String)params.get(GSParams.COLLECTION);
51 if (collection == null || collection.equals("")) {
52 logger.error("classifierBrowse, need to specify a collection!");
53 return page_response;
54
55 }
56
57 String lang = request.getAttribute(GSXML.LANG_ATT);
58 String uid = request.getAttribute(GSXML.USER_ID_ATT);
59 String to = GSPath.appendLink(collection, service_name);
60
61 // the first part of the response is the service description
62 // for now get this again from the service.
63 // this should be cached somehow later on.
64
65 Element info_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
66 Element info_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_DESCRIBE, to, lang, uid);
67 info_message.appendChild(info_request);
68
69 // also get the format stuff now if there is some
70 Element format_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_FORMAT, to, lang, uid);
71 info_message.appendChild(format_request);
72 // process the requests
73
74 Element info_response = (Element) this.mr.process(info_message);
75
76 // the two responses
77 NodeList responses = info_response.getElementsByTagName(GSXML.RESPONSE_ELEM);
78 Element service_response = (Element)responses.item(0);
79 Element format_response = (Element)responses.item(1);
80
81 Element service_description = (Element)GSXML.getChildByTagName(service_response, GSXML.SERVICE_ELEM);
82 page_response.appendChild(this.doc.importNode(service_description, true));
83
84 // if rt=d, then we are just displaying the service
85 String request_type = (String)params.get(GSParams.REQUEST_TYPE);
86 if (request_type.equals("d")) {
87 //return the page that we have so far
88 return page_response;
89 }
90
91 // get the node that the user has clicked on
92 String classifier_node = (String)params.get(CLASSIFIER_ARG);
93
94 // if the node is not defined, return the page that we have so far
95 if (classifier_node ==null || classifier_node.equals("")) {
96 return page_response;
97 }
98
99 // the id of the classifier is the top id of the selected node
100 String top_id = OID.getTop(classifier_node);
101 HashSet doc_meta_names = new HashSet();
102 HashSet class_meta_names = new HashSet();
103 // add in the defaults
104 doc_meta_names.add("Title");
105 class_meta_names.add("Title");
106
107 // add the format info into the response
108 Element format_elem = (Element)GSXML.getChildByTagName(format_response, GSXML.FORMAT_ELEM);
109 if (format_elem != null) {
110
111 // find the one for the classifier we are in
112 Element this_format = GSXML.getNamedElement(format_elem, GSXML.CLASSIFIER_ELEM, GSXML.NAME_ATT, top_id);
113 if (this_format == null) {
114 this_format = (Element)GSXML.getChildByTagName(format_elem, GSXML.DEFAULT_ELEM);
115 }
116
117 if (this_format != null) {
118 Element new_format = GSXML.duplicateWithNewName(this.doc, this_format, GSXML.FORMAT_ELEM, false);
119 extractMetadataNames(new_format, doc_meta_names, class_meta_names);
120 // set the format type
121 new_format.setAttribute(GSXML.TYPE_ATT, "browse");
122
123 page_response.appendChild(new_format);
124 }
125 }
126
127 // find out if this classifier is horizontal at top
128 Element class_list = (Element)GSXML.getChildByTagName(service_description, GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
129 Element this_classifier = GSXML.getNamedElement(class_list, GSXML.CLASSIFIER_ELEM, GSXML.NAME_ATT, top_id);
130 boolean horizontal_at_top = false;
131 if (!this_classifier.getAttribute("horizontalAtTop").equals("")) {
132 horizontal_at_top = true;
133 }
134 if (top_id.equals(classifier_node) && horizontal_at_top) {
135 // we have asked for a top node - if the first list is horizontal, we will select the first element of that list
136 // this is a hack. also it craps out if the classifier really isn't horizontalAtTop. -
137 classifier_node = classifier_node+".1";
138
139 }
140
141 // get the browse structure for the selected node
142 Element classify_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
143 Element classify_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
144 classify_message.appendChild(classify_request);
145
146 //Create a parameter list to specify the required structure information
147 // for now, always get ancestors and children
148 Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
149 classify_request.appendChild(param_list);
150 Element param = this.doc.createElement(GSXML.PARAM_ELEM);
151 param_list.appendChild(param);
152 param.setAttribute(GSXML.NAME_ATT, "structure");
153 param.setAttribute(GSXML.VALUE_ATT, "ancestors");
154 param = this.doc.createElement(GSXML.PARAM_ELEM);
155 param_list.appendChild(param);
156 param.setAttribute(GSXML.NAME_ATT, "structure");
157 param.setAttribute(GSXML.VALUE_ATT, "children");
158
159 // put the classifier node into a classifier node list
160 Element classifier_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
161 Element classifier = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
162 classifier.setAttribute(GSXML.NODE_ID_ATT, classifier_node);
163 classifier_list.appendChild(classifier);
164 classify_request.appendChild(classifier_list);
165
166 if (horizontal_at_top && !classifier_node.equals(top_id)) {
167 // also put the top id in, to get the persistant horizontal info
168 classifier = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
169 classifier.setAttribute(GSXML.NODE_ID_ATT, top_id);
170 classifier_list.appendChild(classifier);
171 }
172 // process the request
173 Element classify_response = (Element)this.mr.process(classify_message);
174 String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
175 Element class_node_list = (Element)GSXML.getNodeByPath(classify_response, path);
176
177 path = GSPath.appendLink(GSXML.CLASS_NODE_ELEM, GSXML.NODE_STRUCTURE_ELEM);
178 // assume that we always get back the top level CL1 node - this becomes the page_classifier node
179 path = GSPath.appendLink(path, GSXML.CLASS_NODE_ELEM);
180 Element cl_structure = (Element)GSXML.getNodeByPath(class_node_list,
181 path);
182 if (cl_structure ==null) {
183 logger.error("classifier structure request returned no structure");
184 return page_response;
185 }
186
187 Element page_classifier = null;
188 if (horizontal_at_top && !classifier_node.equals(top_id)) {
189 // get the info for the top node
190 Element top_node = GSXML.getNamedElement(class_node_list, GSXML.CLASS_NODE_ELEM, GSXML.NODE_ID_ATT, top_id);
191 if (top_node !=null) {
192 path = GSPath.appendLink(GSXML.NODE_STRUCTURE_ELEM, GSXML.CLASS_NODE_ELEM);
193 Element top_structure = (Element)GSXML.getNodeByPath(top_node, path);
194 // add this as the classifier elem
195 page_classifier = GSXML.duplicateWithNewName(this.doc, top_structure, GSXML.CLASSIFIER_ELEM, true);
196 page_response.appendChild(page_classifier);
197 // now replace the child with the structure from the other request
198 Element new_classifier = (Element)GSXML.getChildByTagName(cl_structure, GSXML.CLASS_NODE_ELEM);
199 String replace_name = new_classifier.getAttribute(GSXML.NODE_ID_ATT);
200
201 // find the appropriate child
202 Element old_classifier = GSXML.getNamedElement(page_classifier, GSXML.CLASS_NODE_ELEM, GSXML.NODE_ID_ATT, replace_name);
203 page_classifier.replaceChild(this.doc.importNode(new_classifier, true), old_classifier);
204 page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
205 } else {
206 // add the single classifier node as the page classifier
207 page_classifier = GSXML.duplicateWithNewName(this.doc, cl_structure, GSXML.CLASSIFIER_ELEM, true);
208 page_response.appendChild(page_classifier);
209 page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
210 }
211
212 } else {
213 // add the single classifier node as the page classifier
214 page_classifier = GSXML.duplicateWithNewName(this.doc, cl_structure, GSXML.CLASSIFIER_ELEM, true);
215 page_response.appendChild(page_classifier);
216 page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
217 }
218 // get the metadata for each classifier node,
219 // then for each document node
220
221 Element metadata_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
222
223 boolean did_classifier = false;
224 boolean did_documents = false;
225
226
227 // if there are classifier nodes
228 // create a metadata request for the classifier, and add it to
229 // the the message
230 NodeList cl_nodes = page_classifier.getElementsByTagName(GSXML.CLASS_NODE_ELEM);
231
232 if (cl_nodes.getLength() > 0) {
233 did_classifier = true;
234 Element cl_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to+"MetadataRetrieve", lang, uid);
235 metadata_message.appendChild(cl_meta_request);
236
237 Element new_cl_nodes_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
238 cl_meta_request.appendChild(new_cl_nodes_list);
239
240 for (int c=0; c<cl_nodes.getLength(); c++) {
241
242 Element cl = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
243 cl.setAttribute(GSXML.NODE_ID_ATT, ((Element)cl_nodes.item(c)).getAttribute(GSXML.NODE_ID_ATT));
244 new_cl_nodes_list.appendChild(cl);
245 }
246
247 // create and add in the param list - for now get all the metadata
248 // should be based on info sent in from the recept, and the
249 // format stuff
250 Element cl_param_list = createMetadataParamList(class_meta_names);
251 cl_meta_request.appendChild(cl_param_list);
252
253 }
254
255 // if there are document nodes in the classification (happens
256 // sometimes), create a second request for document metadata and
257 // append to the message
258 NodeList doc_nodes = page_classifier.getElementsByTagName(GSXML.DOC_NODE_ELEM);
259 if (doc_nodes.getLength() > 0) {
260 did_documents = true;
261 Element doc_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, GSPath.appendLink(collection, "DocumentMetadataRetrieve"), lang, uid);
262 metadata_message.appendChild(doc_meta_request);
263
264 Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
265 doc_meta_request.appendChild(doc_list);
266
267 for (int c=0; c<doc_nodes.getLength(); c++) {
268
269 Element d = this.doc.createElement(GSXML.DOC_NODE_ELEM);
270 d.setAttribute(GSXML.NODE_ID_ATT, ((Element)doc_nodes.item(c)).getAttribute(GSXML.NODE_ID_ATT));
271 doc_list.appendChild(d);
272 }
273
274 // create and add in the param list - add all for now
275 Element doc_param_list = createMetadataParamList(doc_meta_names);
276 doc_meta_request.appendChild(doc_param_list);
277
278 }
279
280 // process the metadata requests
281 Element metadata_response = (Element)this.mr.process(metadata_message);
282 if (did_classifier) {
283 // the classifier one will be the first response
284 // add the metadata lists for each node back into the
285 // page_classifier nodes
286 path = GSPath.appendLink(GSXML.RESPONSE_ELEM,
287 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
288 Node pathNode = GSXML.getNodeByPath(metadata_response, path);
289 if (pathNode ==null){
290 return page_response;
291 }
292 NodeList meta_response_cls = pathNode.getChildNodes();
293 for (int i = 0; i < cl_nodes.getLength(); i++) {
294 GSXML.mergeMetadataLists(cl_nodes.item(i), meta_response_cls.item(i));
295
296 }
297 }
298
299 if (did_documents) {
300 NodeList meta_response_docs = null;
301 if (!did_classifier) {
302 // its the first response
303 path = GSPath.appendLink(GSXML.RESPONSE_ELEM,
304 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
305 Node pathNode = GSXML.getNodeByPath(metadata_response, path);
306 if (pathNode ==null){
307 return page_response;
308 }
309
310 meta_response_docs = pathNode.getChildNodes();
311
312
313 } else { // its the second response
314 Node nodes = GSXML.getChildByTagName(metadata_response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(1), GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
315 if (nodes ==null){
316 return page_response;
317 }
318 meta_response_docs = nodes.getChildNodes();
319 }
320
321 for (int i = 0; i < doc_nodes.getLength(); i++) {
322 GSXML.mergeMetadataLists(doc_nodes.item(i), meta_response_docs.item(i));
323 }
324 }
325
326
327 logger.debug("(GS2BrowseAction) Page:\n" + this.converter.getPrettyString(page_response));
328 return page_response;
329 }
330
331
332 protected void extractMetadataNames(Element new_format, HashSet doc_meta_names, HashSet class_meta_names) {
333
334 NodeList templates = new_format.getElementsByTagName("gsf:template");
335 for (int i=0; i<templates.getLength(); i++) {
336 Element template = (Element)templates.item(i);
337 String match = template.getAttribute("match");
338 if (match.equals("documentNode")) {
339 extractMetadataNames(template, doc_meta_names);
340 } else if (match.equals("classifierNode")) {
341 extractMetadataNames(template, class_meta_names);
342 }
343 }
344 }
345
346}
347
348
Note: See TracBrowser for help on using the repository browser.