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

Last change on this file since 21928 was 21928, checked in by ak19, 14 years ago

Kathy improved some code to deal with my converting formatted strings (containing newlines) into XML (so that it contains empty elements).

  • 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;
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 //append site metadata
85 addSiteMetadata( page_response, lang, uid);
86
87 // if rt=d, then we are just displaying the service
88 String request_type = (String)params.get(GSParams.REQUEST_TYPE);
89 if (request_type.equals("d")) {
90 //return the page that we have so far
91 return page_response;
92 }
93
94 // get the node that the user has clicked on
95 String classifier_node = (String)params.get(CLASSIFIER_ARG);
96
97 // if the node is not defined, return the page that we have so far
98 if (classifier_node ==null || classifier_node.equals("")) {
99 return page_response;
100 }
101
102 // the id of the classifier is the top id of the selected node
103 String top_id = OID.getTop(classifier_node);
104 HashSet doc_meta_names = new HashSet();
105 HashSet class_meta_names = new HashSet();
106 // add in the defaults
107 doc_meta_names.add("Title");
108 class_meta_names.add("Title");
109
110 // add the format info into the response
111 Element format_elem = (Element)GSXML.getChildByTagName(format_response, GSXML.FORMAT_ELEM);
112 if (format_elem != null) {
113
114 // find the one for the classifier we are in
115 Element this_format = GSXML.getNamedElement(format_elem, GSXML.CLASSIFIER_ELEM, GSXML.NAME_ATT, top_id);
116 if (this_format == null) {
117 this_format = (Element)GSXML.getChildByTagName(format_elem, GSXML.DEFAULT_ELEM);
118 }
119
120 if (this_format != null) {
121 Element new_format = GSXML.duplicateWithNewName(this.doc, this_format, GSXML.FORMAT_ELEM, false);
122 extractMetadataNames(new_format, doc_meta_names, class_meta_names);
123 // set the format type
124 new_format.setAttribute(GSXML.TYPE_ATT, "browse");
125
126 page_response.appendChild(new_format);
127 }
128 }
129
130 // find out if this classifier is horizontal at top
131 Element class_list = (Element)GSXML.getChildByTagName(service_description, GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
132 Element this_classifier = GSXML.getNamedElement(class_list, GSXML.CLASSIFIER_ELEM, GSXML.NAME_ATT, top_id);
133 boolean horizontal_at_top = false;
134 if (!this_classifier.getAttribute("horizontalAtTop").equals("")) {
135 horizontal_at_top = true;
136 }
137 if (top_id.equals(classifier_node) && horizontal_at_top) {
138 // we have asked for a top node - if the first list is horizontal, we will select the first element of that list
139 // this is a hack. also it craps out if the classifier really isn't horizontalAtTop. -
140 classifier_node = classifier_node+".1";
141
142 }
143
144 // get the browse structure for the selected node
145 Element classify_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
146 Element classify_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to, lang, uid);
147 classify_message.appendChild(classify_request);
148
149 //Create a parameter list to specify the required structure information
150 // for now, always get ancestors and children
151 Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
152 classify_request.appendChild(param_list);
153 Element param = this.doc.createElement(GSXML.PARAM_ELEM);
154 param_list.appendChild(param);
155 param.setAttribute(GSXML.NAME_ATT, "structure");
156 param.setAttribute(GSXML.VALUE_ATT, "ancestors");
157 param = this.doc.createElement(GSXML.PARAM_ELEM);
158 param_list.appendChild(param);
159 param.setAttribute(GSXML.NAME_ATT, "structure");
160 param.setAttribute(GSXML.VALUE_ATT, "children");
161
162 // put the classifier node into a classifier node list
163 Element classifier_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
164 Element classifier = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
165 classifier.setAttribute(GSXML.NODE_ID_ATT, classifier_node);
166 classifier_list.appendChild(classifier);
167 classify_request.appendChild(classifier_list);
168
169 if (horizontal_at_top && !classifier_node.equals(top_id)) {
170 // also put the top id in, to get the persistant horizontal info
171 classifier = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
172 classifier.setAttribute(GSXML.NODE_ID_ATT, top_id);
173 classifier_list.appendChild(classifier);
174 }
175 // process the request
176 Element classify_response = (Element)this.mr.process(classify_message);
177 String path = GSPath.appendLink(GSXML.RESPONSE_ELEM, GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
178 Element class_node_list = (Element)GSXML.getNodeByPath(classify_response, path);
179
180 path = GSPath.appendLink(GSXML.CLASS_NODE_ELEM, GSXML.NODE_STRUCTURE_ELEM);
181 // assume that we always get back the top level CL1 node - this becomes the page_classifier node
182 path = GSPath.appendLink(path, GSXML.CLASS_NODE_ELEM);
183 Element cl_structure = (Element)GSXML.getNodeByPath(class_node_list,
184 path);
185 if (cl_structure ==null) {
186 logger.error("classifier structure request returned no structure");
187 return page_response;
188 }
189
190 Element page_classifier = null;
191 if (horizontal_at_top && !classifier_node.equals(top_id)) {
192 // get the info for the top node
193 Element top_node = GSXML.getNamedElement(class_node_list, GSXML.CLASS_NODE_ELEM, GSXML.NODE_ID_ATT, top_id);
194 if (top_node !=null) {
195 path = GSPath.appendLink(GSXML.NODE_STRUCTURE_ELEM, GSXML.CLASS_NODE_ELEM);
196 Element top_structure = (Element)GSXML.getNodeByPath(top_node, path);
197 // add this as the classifier elem
198 page_classifier = GSXML.duplicateWithNewName(this.doc, top_structure, GSXML.CLASSIFIER_ELEM, true);
199 page_response.appendChild(page_classifier);
200 // now replace the child with the structure from the other request
201 Element new_classifier = (Element)GSXML.getChildByTagName(cl_structure, GSXML.CLASS_NODE_ELEM);
202 String replace_name = new_classifier.getAttribute(GSXML.NODE_ID_ATT);
203
204 // find the appropriate child
205 Element old_classifier = GSXML.getNamedElement(page_classifier, GSXML.CLASS_NODE_ELEM, GSXML.NODE_ID_ATT, replace_name);
206 page_classifier.replaceChild(this.doc.importNode(new_classifier, true), old_classifier);
207 page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
208 } else {
209 // add the single classifier node as the page classifier
210 page_classifier = GSXML.duplicateWithNewName(this.doc, cl_structure, GSXML.CLASSIFIER_ELEM, true);
211 page_response.appendChild(page_classifier);
212 page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
213 }
214
215 } else {
216 // add the single classifier node as the page classifier
217 page_classifier = GSXML.duplicateWithNewName(this.doc, cl_structure, GSXML.CLASSIFIER_ELEM, true);
218 page_response.appendChild(page_classifier);
219 page_classifier.setAttribute(GSXML.NAME_ATT, top_id);
220 }
221 // get the metadata for each classifier node,
222 // then for each document node
223
224 Element metadata_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
225
226 boolean did_classifier = false;
227 boolean did_documents = false;
228
229
230 // if there are classifier nodes
231 // create a metadata request for the classifier, and add it to
232 // the the message
233 NodeList cl_nodes = page_classifier.getElementsByTagName(GSXML.CLASS_NODE_ELEM);
234
235 if (cl_nodes.getLength() > 0) {
236 did_classifier = true;
237 Element cl_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, to+"MetadataRetrieve", lang, uid);
238 metadata_message.appendChild(cl_meta_request);
239
240 Element new_cl_nodes_list = this.doc.createElement(GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
241 cl_meta_request.appendChild(new_cl_nodes_list);
242
243 for (int c=0; c<cl_nodes.getLength(); c++) {
244
245 Element cl = this.doc.createElement(GSXML.CLASS_NODE_ELEM);
246 cl.setAttribute(GSXML.NODE_ID_ATT, ((Element)cl_nodes.item(c)).getAttribute(GSXML.NODE_ID_ATT));
247 new_cl_nodes_list.appendChild(cl);
248 }
249
250 // create and add in the param list - for now get all the metadata
251 // should be based on info sent in from the recept, and the
252 // format stuff
253 Element cl_param_list = createMetadataParamList(class_meta_names);
254 cl_meta_request.appendChild(cl_param_list);
255
256 }
257
258 // if there are document nodes in the classification (happens
259 // sometimes), create a second request for document metadata and
260 // append to the message
261 NodeList doc_nodes = page_classifier.getElementsByTagName(GSXML.DOC_NODE_ELEM);
262 if (doc_nodes.getLength() > 0) {
263 did_documents = true;
264 Element doc_meta_request = GSXML.createBasicRequest(this.doc, GSXML.REQUEST_TYPE_PROCESS, GSPath.appendLink(collection, "DocumentMetadataRetrieve"), lang, uid);
265 metadata_message.appendChild(doc_meta_request);
266
267 Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
268 doc_meta_request.appendChild(doc_list);
269
270 for (int c=0; c<doc_nodes.getLength(); c++) {
271
272 Element d = this.doc.createElement(GSXML.DOC_NODE_ELEM);
273 d.setAttribute(GSXML.NODE_ID_ATT, ((Element)doc_nodes.item(c)).getAttribute(GSXML.NODE_ID_ATT));
274 doc_list.appendChild(d);
275 }
276
277 // create and add in the param list - add all for now
278 Element doc_param_list = createMetadataParamList(doc_meta_names);
279 doc_meta_request.appendChild(doc_param_list);
280
281 }
282
283 // process the metadata requests
284 Element metadata_response = (Element)this.mr.process(metadata_message);
285 if (did_classifier) {
286 // the classifier one will be the first response
287 // add the metadata lists for each node back into the
288 // page_classifier nodes
289 path = GSPath.appendLink(GSXML.RESPONSE_ELEM,
290 GSXML.CLASS_NODE_ELEM+GSXML.LIST_MODIFIER);
291 Node pathNode = GSXML.getNodeByPath(metadata_response, path);
292 if (pathNode ==null){
293 return page_response;
294 }
295 //NodeList meta_response_cls = (Element)pathNode.getChildNodes(); // can't handle empty elements from converting formatted strings (with empty newlines) into XML
296 NodeList meta_response_cls = ((Element)pathNode).getElementsByTagName(GSXML.CLASS_NODE_ELEM);
297 for (int i = 0; i < cl_nodes.getLength(); i++) {
298 GSXML.mergeMetadataLists(cl_nodes.item(i), meta_response_cls.item(i));
299 }
300 }
301
302 if (did_documents) {
303 NodeList meta_response_docs = null;
304 if (!did_classifier) {
305 // its the first response
306 path = GSPath.appendLink(GSXML.RESPONSE_ELEM,
307 GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
308 Node pathNode = GSXML.getNodeByPath(metadata_response, path);
309 if (pathNode ==null){
310 return page_response;
311 }
312
313 meta_response_docs = pathNode.getChildNodes();
314
315
316 } else { // its the second response
317 Node nodes = GSXML.getChildByTagName(metadata_response.getElementsByTagName(GSXML.RESPONSE_ELEM).item(1), GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
318 if (nodes ==null){
319 return page_response;
320 }
321 meta_response_docs = nodes.getChildNodes();
322 }
323
324 for (int i = 0; i < doc_nodes.getLength(); i++) {
325 GSXML.mergeMetadataLists(doc_nodes.item(i), meta_response_docs.item(i));
326 }
327 }
328
329
330 logger.debug("(GS2BrowseAction) Page:\n" + this.converter.getPrettyString(page_response));
331 return page_response;
332 }
333
334
335 protected void extractMetadataNames(Element new_format, HashSet doc_meta_names, HashSet class_meta_names) {
336
337 NodeList templates = new_format.getElementsByTagName("gsf:template");
338 for (int i=0; i<templates.getLength(); i++) {
339 Element template = (Element)templates.item(i);
340 String match = template.getAttribute("match");
341 if (match.equals("documentNode")) {
342 extractMetadataNames(template, doc_meta_names);
343 } else if (match.equals("classifierNode")) {
344 extractMetadataNames(template, class_meta_names);
345 }
346 }
347 }
348
349}
350
351
Note: See TracBrowser for help on using the repository browser.