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

Last change on this file since 25635 was 25635, checked in by sjm84, 12 years ago

Fixing Greenstone 3's use (or lack thereof) of generics, this was done automatically so we may want to change it over time. This change will also auto-format any files that have not already been formatted.

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