source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/CollectionGroups.java@ 32661

Last change on this file since 32661 was 32661, checked in by kjdon, 5 years ago

when getting the list of collections from a group, use node.getElementsByTagName instead of GSXML.getChildrenByTagName, so that we get all collection in the subgroup as well

File size: 19.9 KB
Line 
1package org.greenstone.gsdl3.service;
2
3import java.io.File;
4
5import org.apache.log4j.Logger;
6import org.greenstone.gsdl3.util.GSFile;
7import org.greenstone.gsdl3.util.GSXML;
8import org.greenstone.gsdl3.util.Request;
9import org.greenstone.gsdl3.util.UserContext;
10import org.greenstone.gsdl3.util.XMLConverter;
11import org.w3c.dom.Document;
12import org.w3c.dom.Element;
13import org.w3c.dom.Node;
14import org.w3c.dom.NodeList;
15
16import java.util.Set;
17
18import javax.xml.xpath.XPathConstants;
19import javax.xml.xpath.XPathExpression;
20import javax.xml.xpath.XPathExpressionException;
21import javax.xml.xpath.XPathFactory;
22
23import java.util.HashSet;
24import java.util.Iterator;
25
26public class CollectionGroups extends ServiceRack {
27
28 private Element hierarchy = null;
29 private Element groupDesc = null;
30
31 public static final String GROUP_CONTENT = "GroupCurrentContent";
32 public static final String UNIQUE_COLLECTIONS = "UniqueCollections";
33 public static final String COLLECTIONS_HIERARCHY = "CollectionsHierarchy";
34
35 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.BerryBasket.class.getName());
36
37 @Override
38 protected Element getServiceDescription(Document doc, String service, String lang, String subset) {
39 // TODO Auto-generated method stub
40 return null;
41 }
42
43 String[] _services = { GROUP_CONTENT, UNIQUE_COLLECTIONS, COLLECTIONS_HIERARCHY };
44
45 public boolean configure(Element info, Element extra_info) {
46 if (!super.configure(info, extra_info)) {
47 return false;
48 }
49
50 logger.info("Configuring CollectionGroups...");
51 this.config_info = info;
52
53 for (int i = 0; i < _services.length; i++) {
54 Element service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
55 service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_GROUPINFO);
56 service.setAttribute(GSXML.NAME_ATT, _services[i]);
57 this.short_service_info.appendChild(service);
58 }
59 // Load group configuration from file
60 return readGroupConfiguration();
61 }
62
63 protected Element processGroupCurrentContent(Element request) {
64
65 Document doc = XMLConverter.newDOM();
66 UserContext userContext = new UserContext(request);
67
68 // Prepare basic response
69 Element result = GSXML.createBasicResponse(doc, GSXML.SERVICE_TYPE_GROUPINFO);
70
71
72 // Get param list from request
73 Element paramList = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
74 // Set default group path (main page)
75 String groupPath = "";
76 // If param list not null and group param exists extract value and
77 // override groupPath variable
78 if (paramList != null) {
79 Element paramGroup = GSXML.getNamedElement(paramList, GSXML.PARAM_ELEM, GSXML.NAME_ATT, GSXML.GROUP_ELEM);
80 if (paramGroup != null) {
81 groupPath = paramGroup.getAttribute(GSXML.VALUE_ATT);
82 }
83 }
84 //Remove leading, ending / and dupliclated /
85 groupPath = groupPath.replaceAll("(/+)", "/");
86 groupPath = groupPath.replaceAll("(^/+)|(/+$)", "");
87
88 Element mrCollectionList = getAvailableCollectionList(userContext);
89 if (mrCollectionList == null){
90 result.appendChild(doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER));
91 return result;
92 }
93 //Get current groups and collections
94 Element groupContent = getRawCurrentContent(groupPath);
95
96 //Get ungrouped collection list
97 Element ungroupedCollections = getUngroupedCollections(mrCollectionList);
98
99 // If groupContent is empty return empty collection list
100 if (groupContent == null) {
101 result.appendChild(doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER));
102 return result;
103 }
104 NodeList currentContent = groupContent.getChildNodes();
105 if (currentContent != null && currentContent.getLength() > 0) {
106 // Create CollectionList element in response
107 Element result_collection_list = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
108 result.appendChild(result_collection_list);
109 Element result_group_list = doc.createElement(GSXML.GROUP_ELEM + GSXML.LIST_MODIFIER);
110 result.appendChild(result_group_list);
111 // Iterate over collections from current view
112 // i represents current position in groupConfig.xml
113 int i;
114 for (i=0; i < currentContent.getLength(); i++) {
115 //logger.warn("NODE CuR Content" + GSXML.xmlNodeToString(currentContent.item(i)));
116
117 if (currentContent.item(i).getNodeName() == GSXML.COLLECTION_ELEM) {
118
119 Element collection = (Element) currentContent.item(i);
120 String collection_name = collection.getAttribute(GSXML.NAME_ATT);
121 // Check whether collection from current view exists in message router response
122 Element checkedCollection = GSXML.getNamedElement(mrCollectionList, GSXML.COLLECTION_ELEM,GSXML.NAME_ATT, collection_name);
123 if (checkedCollection != null) {
124 //Set position value
125 checkedCollection.setAttribute(GSXML.POSITION_ATT, String.valueOf(i));
126 // Add collection to response
127 result_collection_list.appendChild(doc.importNode(checkedCollection, true));
128 }
129
130 //Iterate over groups in current view
131 } else if (currentContent.item(i).getNodeName() == GSXML.GROUP_ELEM) {
132 Element currentGroup = (Element) currentContent.item(i);
133 String currentGroupName = currentGroup.getAttribute(GSXML.NAME_ATT);
134 Element groupDescription = getGroupDescription(currentGroupName);
135
136 groupDescription.setAttribute(GSXML.POSITION_ATT, String.valueOf(i));
137 result_group_list.appendChild(doc.importNode(groupDescription, true));
138 }
139
140 }
141 //Add ungrouped collections if groupPath /+ or "" or null
142 if (groupPath.isEmpty()) {
143
144 //Add each ungrouped collection to the collection list in loop
145 NodeList ungroupedCollectionNodes = GSXML.getChildrenByTagName(ungroupedCollections, GSXML.COLLECTION_ATT);
146 if (ungroupedCollectionNodes != null) {
147 for (int j = 0; j < ungroupedCollectionNodes.getLength(); j++) {
148 //logger.warn("UNGROUPED COLL ELEM" + GSXML.xmlNodeToString(ungroupedCollections).intern());
149 Element ungroupedCollection = (Element) doc.importNode(ungroupedCollectionNodes.item(j), true);
150 ungroupedCollection.setAttribute(GSXML.POSITION_ATT, String.valueOf(i++));
151 result_collection_list.appendChild(ungroupedCollection);
152 }
153 }
154
155 } else {
156 Element groupDescription = getPathInfo(groupPath);
157 if (groupContent != null){
158 result.appendChild(doc.importNode(groupDescription, true));
159 }
160 }
161 }
162
163 return result;
164 }
165
166 protected Element processUniqueCollections(Element request) {
167 Document doc = XMLConverter.newDOM();
168 UserContext userContext = new UserContext(request);
169 // Prepare basic response
170 Element result = GSXML.createBasicResponse(doc, GSXML.SERVICE_TYPE_GROUPINFO);
171 Element resultCollections = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
172 result.appendChild(resultCollections);
173 Element mrCollectionList = getAvailableCollectionList(userContext);
174 //Collections from message router check
175 if (mrCollectionList == null){
176 logger.error("mrCollectionList is null!");
177 return result;
178 }
179 //paramList check
180 Element paramList = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
181 if (paramList == null) {
182 logger.error("UniqueCollections request had no paramList.");
183 return result;
184 }
185 //Add collections from request
186 Set<String> uniq_colls = new HashSet<String>();
187 Element collParam = GSXML.getNamedElement(paramList, GSXML.PARAM_ELEM, GSXML.NAME_ATT, GSXML.COLLECTION_ELEM);
188 if (collParam != null){
189 String colls = GSXML.getValue(collParam);
190 if (!colls.isEmpty())
191 {
192 String[] _colls = colls.split(",");
193 for (int i=0;i < _colls.length;i++){
194 uniq_colls.add(_colls[i]);
195 }
196 }
197 }
198 //groupParam check
199 Element groupParam = GSXML.getNamedElement(paramList, GSXML.PARAM_ELEM, GSXML.NAME_ATT, GSXML.GROUP_ELEM);
200 if (groupParam == null) {
201 logger.error("UniqueCollections request had no groupParam.");
202 return result;
203 }
204 //Add collections from groups
205 String[] groups = null;
206 groups = GSXML.getValue(groupParam).split(",");
207 for (int i = 0; i < groups.length; i++) {
208 if (!groups[i].isEmpty()) {
209 Element groupContent = getRawCurrentContent(groups[i]);
210 // If group exists
211 if (groupContent != null) {
212 NodeList collectionNodes = groupContent.getElementsByTagName(GSXML.COLLECTION_ELEM);
213 for (int j = 0; j < collectionNodes.getLength(); j++) {
214 String collName = ((Element) collectionNodes.item(j)).getAttribute(GSXML.NAME_ATT);
215 uniq_colls.add(collName);
216 }
217 }
218 }
219
220 }
221 //Fill result collectionList
222 for (Iterator<String> iterator = uniq_colls.iterator(); iterator.hasNext();) {
223 String collectionName = (String) iterator.next();
224 Element checkedCollection = GSXML.getNamedElement(mrCollectionList, GSXML.COLLECTION_ELEM,GSXML.NAME_ATT, collectionName);
225 if (checkedCollection != null){
226 resultCollections.appendChild(doc.importNode(checkedCollection, true));
227 }
228 }
229 return result;
230
231 }
232
233 protected Element processCollectionsHierarchy(Element request){
234
235 Document doc = XMLConverter.newDOM();
236 UserContext userContext = new UserContext(request);
237 // Prepare basic response
238 Element result = GSXML.createBasicResponse(doc, GSXML.SERVICE_TYPE_GROUPINFO);
239 String currentPath = "";
240 Element currentContent = getRawCurrentContent(currentPath);
241 if (currentContent == null){
242 return result;
243 }
244 Element searchableCollectionList = getSearchableCollectionList(userContext);
245 if (searchableCollectionList == null){
246 return result;
247 }
248
249 //Get ungrouped collection list
250 sanitizeCurrentContent(currentContent, searchableCollectionList);
251 addGroupInfo(currentContent, currentPath);
252 addUngroupedCollections(currentContent, searchableCollectionList);
253 addAllOption(currentContent);
254 result.appendChild(doc.importNode(currentContent, true));
255 return result;
256 }
257
258 private void addAllOption(Element currentContent) {
259 if (currentContent == null){
260 return;
261 }
262 Document doc = currentContent.getOwnerDocument();
263 Element allOption = doc.createElement(GSXML.COLLECTION_ELEM);
264 allOption.setAttribute(GSXML.NAME_ATT, "all");
265 if (currentContent.hasChildNodes()){
266 currentContent.insertBefore(allOption,currentContent.getFirstChild());
267 } else
268 currentContent.appendChild(allOption);
269
270
271 }
272
273 private void addGroupInfo(Element currentContent, String groupPath) {
274 NodeList groups = GSXML.getChildrenByTagName(currentContent,GSXML.GROUP_ELEM);
275 for (int i=0;i<groups.getLength();i++){
276 Element group = (Element) groups.item(i);
277 String name = group.getAttribute(GSXML.NAME_ATT);
278 String newPath = groupPath + "/" + name;
279 group.setAttribute(GSXML.PATH_ATT, newPath);
280 Element groupDescription = getGroupDescription(name);
281 Element titleEl = (Element) GSXML.getChildByTagName(groupDescription, GSXML.TITLE_ELEM);
282 String title;
283 if (titleEl != null) {
284 title = titleEl.getTextContent();
285 } else {
286 title = name;
287 }
288 group.setAttribute(GSXML.TITLE_ELEM, title );
289 addGroupInfo(group, newPath);
290 }
291
292 }
293
294 private Element getRawCurrentContent(String path) {
295
296 if (path == null) {
297 path = "";
298 }
299
300 Document doc = XMLConverter.newDOM();
301 path = path.replaceAll("(/+)", "/");
302 path = path.replaceAll("(^/+)|(/+$)", "");
303
304 String[] pathSteps = path.split("/");
305
306
307 Element currentContent = (Element) hierarchy.cloneNode(true);
308 // Get the current view
309 for (int i = 0; i < pathSteps.length; i++) {
310 if (!pathSteps[i].isEmpty()) {
311 currentContent = GSXML.getNamedElement(currentContent, GSXML.GROUP_ELEM, GSXML.NAME_ATT, pathSteps[i]);
312 if (currentContent == null){
313 break;
314 }
315 }
316 }
317 if (currentContent == null || !currentContent.hasChildNodes()) {
318 // Return to the main page
319 return null;
320 }
321 return currentContent;
322 }
323
324 private void sanitizeCurrentContent(Element currentContent, Element checkedCollectionList){
325 if (currentContent == null){
326 return;
327 }
328 NodeList nodes = currentContent.getElementsByTagName(GSXML.COLLECTION_ELEM);
329 for (int i = 0; i < nodes.getLength(); i++) {
330 Element element = (Element) nodes.item(i);
331 String name = element.getAttribute(GSXML.NAME_ATT);
332 Element checkedCollection = GSXML.getNamedElement(checkedCollectionList, GSXML.COLLECTION_ELEM, GSXML.NAME_ATT, name);
333 if (checkedCollection == null) {
334 element.getParentNode().removeChild(element);
335 i--;
336 }
337 }
338 }
339
340 private void addUngroupedCollections(Element currentContent, Element availableCollections){
341 if (currentContent == null){
342 return;
343 }
344 Document doc = currentContent.getOwnerDocument();
345 NodeList collectionList = availableCollections.getElementsByTagName(GSXML.COLLECTION_ELEM);
346 for (int i = 0; i < collectionList.getLength();i++){
347 Element collection = (Element) collectionList.item(i);
348 String name = collection.getAttribute(GSXML.NAME_ATT);
349 NodeList foundCollection = GSXML.getNamedElements(currentContent, GSXML.COLLECTION_ELEM, GSXML.NAME_ATT, name);
350 if (foundCollection.getLength() == 0){
351 Element ungroupedCollection = doc.createElement(GSXML.COLLECTION_ELEM);
352 ungroupedCollection.setAttribute(GSXML.NAME_ATT, name);
353 currentContent.appendChild(ungroupedCollection);
354 }
355 }
356
357 }
358
359 private boolean readGroupConfiguration() {
360
361 File configFile = new File(GSFile.groupConfigFile(site_home));
362 //
363 if (!configFile.exists()) {
364 logger.info("Groups config file " + configFile.getPath() + " does not exist.");
365 return false;
366 }
367 Document doc;
368 Element content;
369 try {
370 doc = XMLConverter.getDOM(configFile);
371 content = doc.getDocumentElement();
372 } catch (Exception e) {
373 System.out.println(e.getClass());
374 e.printStackTrace();
375 return false;
376 }
377 // XPath to find empty text nodes.
378 try {
379 XPathFactory xpathFactory = XPathFactory.newInstance();
380 XPathExpression xpathExp = xpathFactory.newXPath().compile("//text()[normalize-space(.) = '']");
381 NodeList emptyTextNodes = (NodeList) xpathExp.evaluate(doc, XPathConstants.NODESET);
382 for (int i = 0; i < emptyTextNodes.getLength(); i++) {
383 Node emptyTextNode = emptyTextNodes.item(i);
384 emptyTextNode.getParentNode().removeChild(emptyTextNode);
385 }
386
387 } catch (XPathExpressionException e) {
388 logger.error("Error occurred while trying to remove emtpy nodes from groupConfig.xml");
389 e.printStackTrace();
390 return false;
391 }
392
393 hierarchy = (Element) GSXML.getChildByTagName(content, GSXML.HIERARCHY_ELEM);
394 groupDesc = (Element) GSXML.getChildByTagName(content, GSXML.GROUP_DESC_ELEM);
395 if (hierarchy == null){
396 logger.error("<groupConfig> has no <hierarchy> element, ignoring it.");
397 return false;
398 }
399 verifyGroupDescription(doc);
400 return true;
401 }
402
403 private void verifyGroupDescription(Document doc) {
404 if (groupDesc == null) {
405 // we set up one for ourselves
406 groupDesc = doc.createElement(GSXML.GROUP_DESC_ELEM);
407 }
408
409 // Document doc = groupDesc.getOwnerDocument();
410 NodeList groups = hierarchy.getElementsByTagName(GSXML.GROUP_ELEM);
411 for (int i = 0; i < groups.getLength(); i++) {
412 Element group = (Element) groups.item(i);
413 String name = group.getAttribute(GSXML.NAME_ATT);
414 Element foundDescription = GSXML.getNamedElement(groupDesc, GSXML.GROUP_ELEM, GSXML.NAME_ATT, name);
415 if (foundDescription == null){
416 Element defaultDescription = doc.createElement(GSXML.GROUP_ELEM);
417 defaultDescription.setAttribute(GSXML.NAME_ATT, name);
418 Element groupTitle = doc.createElement(GSXML.TITLE_ELEM);
419 groupTitle.setTextContent(name);
420 defaultDescription.appendChild(groupTitle);
421 groupDesc.appendChild(defaultDescription);
422 }
423 }
424
425 }
426
427 private Element getGroupDescription(String name) {
428 Element description = (Element) GSXML.getNamedElement(groupDesc, GSXML.GROUP_ELEM, GSXML.NAME_ATT, name);
429 if (description == null) {
430 logger.error("GroupDescription is not defined. Check your groupConfig.xml");
431 }
432 return description;
433 }
434
435 private Element getUngroupedCollections(Element mr_collection_list) {
436
437 Document doc = XMLConverter.newDOM();
438 // Create Set
439 Set<String> hierarchy_unique_collections = new HashSet<String>();
440 // Element hierarchyCollections = doc.createElement("coll_list");
441 // Get collection nodes
442
443 NodeList hierarchy_all_collection_list = hierarchy.getElementsByTagName(GSXML.COLLECTION_ELEM);
444 // Save hierarchy collection names to Hashset
445 for (int i = 0; i < hierarchy_all_collection_list.getLength(); i++) {
446 Element collection_element = (Element) hierarchy_all_collection_list.item(i);
447 hierarchy_unique_collections.add(collection_element.getAttribute(GSXML.NAME_ATT));
448 }
449 // Save available by message router collection names to Hashset
450 Set<String> mr_collections = new HashSet<String>();
451 NodeList mr_coll_list = mr_collection_list.getElementsByTagName(GSXML.COLLECTION_ELEM);
452
453 for (int i = 0; i < mr_coll_list.getLength(); i++) {
454 Element collection_element = (Element) mr_coll_list.item(i);
455 mr_collections.add(collection_element.getAttribute(GSXML.NAME_ATT));
456 }
457 //Save collections available by message router and not existed in hierarchy to ungrouped collections set
458 Set<String> ungrouped_collections = new HashSet<String>();
459 for (String string : mr_collections) {
460 if (!hierarchy_unique_collections.contains(string)){
461 ungrouped_collections.add(string);
462 }
463 }
464 //Output
465 Element result = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
466 for (String name : ungrouped_collections) {
467 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
468 collection.setAttribute(GSXML.NAME_ATT, name);
469 result.appendChild(collection);
470 }
471 return result;
472
473 }
474 private Element getPathInfo(String path) {
475
476 Document doc = XMLConverter.newDOM();
477
478 if (path == null) {
479 path = "";
480 }
481 String[] pathSteps = path.split("/");
482
483 Element pathInfo = doc.createElement(GSXML.PATH_ELEM + GSXML.LIST_MODIFIER);
484
485 String currentPath = "";
486 boolean first = true;
487 for (int i = 0; i < pathSteps.length; i++) {
488 if (!pathSteps[i].isEmpty()) {
489 if (first) {
490 first = false;
491 } else {
492 currentPath += "/";
493 }
494 currentPath += pathSteps[i];
495 Element pathStepDescription = getGroupDescription(pathSteps[i]);
496 if (pathStepDescription != null){
497 pathStepDescription.setAttribute(GSXML.POSITION_ATT, String.valueOf(i));
498 pathStepDescription.setAttribute(GSXML.PATH_ATT, currentPath);
499 }
500 pathInfo.appendChild(doc.importNode(pathStepDescription, true));
501 }
502 }
503
504 return pathInfo;
505 }
506 private Element getAvailableCollectionList(UserContext userContext){
507 Document doc = XMLConverter.newDOM();
508 // Get the message router info
509 Element inforesponseMessage = new Request(doc, userContext, router, GSXML.REQUEST_TYPE_DESCRIBE).send();
510 if (inforesponseMessage == null) {
511 logger.error(" couldn't query the message router!");
512 return null;
513 }
514 Element mr_info_response = (Element) GSXML.getChildByTagName(inforesponseMessage, GSXML.RESPONSE_ELEM);
515 if (mr_info_response == null) {
516 logger.error("Message router response is null!");
517 return null;
518 }
519
520 Element mr_collection_list = (Element) GSXML.getChildByTagName(mr_info_response, GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
521
522 return mr_collection_list;
523 }
524 private Element getSearchableCollectionList(UserContext userContext){
525 Document doc = XMLConverter.newDOM();
526 Element collectionList = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
527 // Get the message router info
528 Element mr_info_message = doc.createElement(GSXML.MESSAGE_ELEM);
529 Element mr_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_DESCRIBE, "TextQuery" , userContext);
530 mr_info_message.appendChild(mr_request);
531 Element mr_info_response_message = (Element) this.router.process(mr_info_message);
532 if (mr_info_response_message == null) {
533 logger.error(" couldn't query the message router!");
534 return null;
535 }
536 NodeList options = mr_info_response_message.getElementsByTagName(GSXML.PARAM_OPTION_ELEM);
537 for (int i = 0; i < options.getLength(); i++) {
538 Element option = (Element) options.item(i);
539 String name = option.getAttribute(GSXML.NAME_ATT);
540 if (name.equals("all")){
541 continue;
542 }
543 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
544 collection.setAttribute(GSXML.NAME_ATT, name);
545 collectionList.appendChild(collection);
546 }
547 return collectionList;
548 }
549}
Note: See TracBrowser for help on using the repository browser.