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

Last change on this file since 32115 was 32115, checked in by Georgiy Litvinov, 6 years ago

Fixed NPE in case empty group title

File size: 19.6 KB
RevLine 
[30540]1package org.greenstone.gsdl3.service;
2
3import java.io.File;
[31181]4
[30540]5import org.apache.log4j.Logger;
6import org.greenstone.gsdl3.util.GSFile;
7import org.greenstone.gsdl3.util.GSXML;
[32115]8import org.greenstone.gsdl3.util.Request;
[30540]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;
[31181]15
[30540]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;
[31181]24import java.util.Iterator;
[30540]25
26public class CollectionGroups extends ServiceRack {
27
28 private Element hierarchy = null;
29 private Element groupDesc = null;
30
31 private static final String GROUP_CONTENT = "GroupCurrentContent";
[31181]32 private static final String UNIQUE_COLLECTIONS = "UniqueCollections";
[31285]33 private static final String COLLECTIONS_HIERARCHY = "CollectionsHierarchy";
[30540]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
[31285]43 String[] _services = { GROUP_CONTENT, UNIQUE_COLLECTIONS, COLLECTIONS_HIERARCHY };
[30540]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
[31285]60 return readGroupConfiguration();
[30540]61 }
62
63 protected Element processGroupCurrentContent(Element request) {
64
65 Document doc = XMLConverter.newDOM();
66 UserContext userContext = new UserContext(request);
67
[31181]68 // Prepare basic response
69 Element result = GSXML.createBasicResponse(doc, GSXML.SERVICE_TYPE_GROUPINFO);
70
71
[30540]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
[31285]88 Element mrCollectionList = getAvailableCollectionList(userContext);
[31181]89 if (mrCollectionList == null){
90 result.appendChild(doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER));
91 return result;
[30540]92 }
93 //Get current groups and collections
[31285]94 Element groupContent = getRawCurrentContent(groupPath);
[30540]95
96 //Get ungrouped collection list
[31181]97 Element ungroupedCollections = getUngroupedCollections(mrCollectionList);
[30540]98
99 // If groupContent is empty return empty collection list
100 if (groupContent == null) {
[31285]101 result.appendChild(doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER));
[30540]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
[31181]122 Element checkedCollection = GSXML.getNamedElement(mrCollectionList, GSXML.COLLECTION_ELEM,GSXML.NAME_ATT, collection_name);
[30540]123 if (checkedCollection != null) {
[30541]124 //Set position value
125 checkedCollection.setAttribute(GSXML.POSITION_ATT, String.valueOf(i));
[30540]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);
[31285]134 Element groupDescription = getGroupDescription(currentGroupName);
135
136 groupDescription.setAttribute(GSXML.POSITION_ATT, String.valueOf(i));
137 result_group_list.appendChild(doc.importNode(groupDescription, true));
[30540]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
[31166]155 } else {
156 Element groupDescription = getPathInfo(groupPath);
157 if (groupContent != null){
158 result.appendChild(doc.importNode(groupDescription, true));
159 }
[30540]160 }
161 }
162
163 return result;
164 }
165
[31181]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);
[31285]173 Element mrCollectionList = getAvailableCollectionList(userContext);
[31181]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++) {
[31285]208 Element groupContent = getRawCurrentContent(groups[i]);
[31181]209 //If group exists
210 if (groupContent != null) {
211 NodeList collectionNodes = GSXML.getChildrenByTagName(groupContent, GSXML.COLLECTION_ELEM);
212 for (int j = 0; j < collectionNodes.getLength(); j++) {
213 String collName = ((Element) collectionNodes.item(j)).getAttribute(GSXML.NAME_ATT);
214 uniq_colls.add(collName);
215 }
216 }
217
218 }
219 //Fill result collectionList
220 for (Iterator<String> iterator = uniq_colls.iterator(); iterator.hasNext();) {
221 String collectionName = (String) iterator.next();
222 Element checkedCollection = GSXML.getNamedElement(mrCollectionList, GSXML.COLLECTION_ELEM,GSXML.NAME_ATT, collectionName);
223 if (checkedCollection != null){
224 resultCollections.appendChild(doc.importNode(checkedCollection, true));
225 }
226 }
227 return result;
228
229 }
230
[31285]231 protected Element processCollectionsHierarchy(Element request){
[30540]232
233 Document doc = XMLConverter.newDOM();
[31285]234 UserContext userContext = new UserContext(request);
235 // Prepare basic response
236 Element result = GSXML.createBasicResponse(doc, GSXML.SERVICE_TYPE_GROUPINFO);
237 String currentPath = "";
238 Element currentContent = getRawCurrentContent(currentPath);
239 if (currentContent == null){
240 return result;
241 }
242 Element searchableCollectionList = getSearchableCollectionList(userContext);
243 if (searchableCollectionList == null){
244 return result;
245 }
[30540]246
[31285]247 //Get ungrouped collection list
248 sanitizeCurrentContent(currentContent, searchableCollectionList);
249 addGroupInfo(currentContent, currentPath);
250 addUngroupedCollections(currentContent, searchableCollectionList);
[31345]251 addAllOption(currentContent);
[31285]252 result.appendChild(doc.importNode(currentContent, true));
253 return result;
254 }
255
[31345]256 private void addAllOption(Element currentContent) {
257 if (currentContent == null){
258 return;
259 }
260 Document doc = currentContent.getOwnerDocument();
261 Element allOption = doc.createElement(GSXML.COLLECTION_ELEM);
262 allOption.setAttribute(GSXML.NAME_ATT, "all");
263 if (currentContent.hasChildNodes()){
264 currentContent.insertBefore(allOption,currentContent.getFirstChild());
265 } else
266 currentContent.appendChild(allOption);
267
268
269 }
270
[31285]271 private void addGroupInfo(Element currentContent, String groupPath) {
272 NodeList groups = GSXML.getChildrenByTagName(currentContent,GSXML.GROUP_ELEM);
273 for (int i=0;i<groups.getLength();i++){
274 Element group = (Element) groups.item(i);
275 String name = group.getAttribute(GSXML.NAME_ATT);
276 String newPath = groupPath + "/" + name;
277 group.setAttribute(GSXML.PATH_ATT, newPath);
278 Element groupDescription = getGroupDescription(name);
279 Element titleEl = (Element) GSXML.getChildByTagName(groupDescription, GSXML.TITLE_ELEM);
[32115]280 String title;
281 if (titleEl != null) {
282 title = titleEl.getTextContent();
283 } else {
284 title = name;
285 }
[31285]286 group.setAttribute(GSXML.TITLE_ELEM, title );
287 addGroupInfo(group, newPath);
288 }
289
290 }
291
292 private Element getRawCurrentContent(String path) {
293
[30540]294 if (path == null) {
295 path = "";
296 }
[31285]297
298 Document doc = XMLConverter.newDOM();
[31181]299 path = path.replaceAll("(/+)", "/");
300 path = path.replaceAll("(^/+)|(/+$)", "");
301
[30540]302 String[] pathSteps = path.split("/");
303
304
[31285]305 Element currentContent = (Element) hierarchy.cloneNode(true);
[30540]306 // Get the current view
307 for (int i = 0; i < pathSteps.length; i++) {
308 if (!pathSteps[i].isEmpty()) {
[31285]309 currentContent = GSXML.getNamedElement(currentContent, GSXML.GROUP_ELEM, GSXML.NAME_ATT, pathSteps[i]);
310 if (currentContent == null){
[31181]311 break;
312 }
[30540]313 }
314 }
[31285]315 if (currentContent == null || !currentContent.hasChildNodes()) {
[30540]316 // Return to the main page
317 return null;
318 }
[31285]319 return currentContent;
[30540]320 }
[31285]321
322 private void sanitizeCurrentContent(Element currentContent, Element checkedCollectionList){
323 if (currentContent == null){
324 return;
325 }
326 NodeList nodes = currentContent.getElementsByTagName(GSXML.COLLECTION_ELEM);
327 for (int i = 0; i < nodes.getLength(); i++) {
328 Element element = (Element) nodes.item(i);
329 String name = element.getAttribute(GSXML.NAME_ATT);
330 Element checkedCollection = GSXML.getNamedElement(checkedCollectionList, GSXML.COLLECTION_ELEM, GSXML.NAME_ATT, name);
331 if (checkedCollection == null) {
332 element.getParentNode().removeChild(element);
333 i--;
334 }
335 }
336 }
337
338 private void addUngroupedCollections(Element currentContent, Element availableCollections){
339 if (currentContent == null){
340 return;
341 }
342 Document doc = currentContent.getOwnerDocument();
343 NodeList collectionList = availableCollections.getElementsByTagName(GSXML.COLLECTION_ELEM);
344 for (int i = 0; i < collectionList.getLength();i++){
345 Element collection = (Element) collectionList.item(i);
346 String name = collection.getAttribute(GSXML.NAME_ATT);
347 NodeList foundCollection = GSXML.getNamedElements(currentContent, GSXML.COLLECTION_ELEM, GSXML.NAME_ATT, name);
348 if (foundCollection.getLength() == 0){
349 Element ungroupedCollection = doc.createElement(GSXML.COLLECTION_ELEM);
350 ungroupedCollection.setAttribute(GSXML.NAME_ATT, name);
351 currentContent.appendChild(ungroupedCollection);
352 }
353 }
354
355 }
[30540]356
[31285]357 private boolean readGroupConfiguration() {
[30540]358
359 File configFile = new File(GSFile.groupConfigFile(site_home));
360 //
361 if (!configFile.exists()) {
[31109]362 logger.info("Groups config file " + configFile.getPath() + " does not exist.");
[31285]363 return false;
[30540]364 }
365 // Try to read and catch exception if it fails
366 Document doc = XMLConverter.getDOM(configFile);
367 Element content = doc.getDocumentElement();
368
369 // XPath to find empty text nodes.
370 try {
371 XPathFactory xpathFactory = XPathFactory.newInstance();
372 XPathExpression xpathExp = xpathFactory.newXPath().compile("//text()[normalize-space(.) = '']");
373 NodeList emptyTextNodes = (NodeList) xpathExp.evaluate(doc, XPathConstants.NODESET);
374 for (int i = 0; i < emptyTextNodes.getLength(); i++) {
375 Node emptyTextNode = emptyTextNodes.item(i);
376 emptyTextNode.getParentNode().removeChild(emptyTextNode);
377 }
378
379 } catch (XPathExpressionException e) {
380 logger.error("Error occurred while trying to remove emtpy nodes from groupConfig.xml");
381 e.printStackTrace();
[31285]382 return false;
[30540]383 }
384
385 hierarchy = (Element) GSXML.getChildByTagName(content, GSXML.HIERARCHY_ELEM);
386 groupDesc = (Element) GSXML.getChildByTagName(content, GSXML.GROUP_DESC_ELEM);
[31285]387 if (hierarchy == null || groupDesc == null){
[31869]388 logger.error("Error processing groups configuration. <groupConfig> should have both <hierarchy> and <groupDescriptions> elements. Check groupConfig.xml");
[31285]389 return false;
390 }
391 verifyGroupDescription();
392 return true;
[30540]393 }
394
[31285]395 private void verifyGroupDescription() {
396 Document doc = groupDesc.getOwnerDocument();
397 NodeList groups = hierarchy.getElementsByTagName(GSXML.GROUP_ELEM);
398 for (int i = 0; i < groups.getLength(); i++) {
399 Element group = (Element) groups.item(i);
400 String name = group.getAttribute(GSXML.NAME_ATT);
401 Element foundDescription = GSXML.getNamedElement(groupDesc, GSXML.GROUP_ELEM, GSXML.NAME_ATT, name);
402 if (foundDescription == null){
403 Element defaultDescription = doc.createElement(GSXML.GROUP_ELEM);
404 defaultDescription.setAttribute(GSXML.NAME_ATT, name);
405 Element groupTitle = doc.createElement(GSXML.TITLE_ELEM);
406 groupTitle.setTextContent(name);
407 defaultDescription.appendChild(groupTitle);
408 groupDesc.appendChild(defaultDescription);
[30540]409 }
410 }
[31285]411
[30540]412 }
413
[31285]414 private Element getGroupDescription(String name) {
415 Element description = (Element) GSXML.getNamedElement(groupDesc, GSXML.GROUP_ELEM, GSXML.NAME_ATT, name);
416 if (description == null) {
417 logger.error("GroupDescription is not defined. Check your groupConfig.xml");
418 }
419 return description;
420 }
421
[30540]422 private Element getUngroupedCollections(Element mr_collection_list) {
423
424 Document doc = XMLConverter.newDOM();
425 // Create Set
426 Set<String> hierarchy_unique_collections = new HashSet<String>();
427 // Element hierarchyCollections = doc.createElement("coll_list");
428 // Get collection nodes
429
430 NodeList hierarchy_all_collection_list = hierarchy.getElementsByTagName(GSXML.COLLECTION_ELEM);
431 // Save hierarchy collection names to Hashset
432 for (int i = 0; i < hierarchy_all_collection_list.getLength(); i++) {
433 Element collection_element = (Element) hierarchy_all_collection_list.item(i);
434 hierarchy_unique_collections.add(collection_element.getAttribute(GSXML.NAME_ATT));
435 }
436 // Save available by message router collection names to Hashset
437 Set<String> mr_collections = new HashSet<String>();
438 NodeList mr_coll_list = mr_collection_list.getElementsByTagName(GSXML.COLLECTION_ELEM);
439
440 for (int i = 0; i < mr_coll_list.getLength(); i++) {
441 Element collection_element = (Element) mr_coll_list.item(i);
442 mr_collections.add(collection_element.getAttribute(GSXML.NAME_ATT));
443 }
444 //Save collections available by message router and not existed in hierarchy to ungrouped collections set
445 Set<String> ungrouped_collections = new HashSet<String>();
446 for (String string : mr_collections) {
447 if (!hierarchy_unique_collections.contains(string)){
448 ungrouped_collections.add(string);
449 }
450 }
451 //Output
452 Element result = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
453 for (String name : ungrouped_collections) {
454 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
455 collection.setAttribute(GSXML.NAME_ATT, name);
456 result.appendChild(collection);
457 }
458 return result;
459
460 }
[31166]461 private Element getPathInfo(String path) {
[30540]462
[31166]463 Document doc = XMLConverter.newDOM();
464
465 if (path == null) {
466 path = "";
467 }
468 String[] pathSteps = path.split("/");
469
470 Element pathInfo = doc.createElement(GSXML.PATH_ELEM + GSXML.LIST_MODIFIER);
471
472 String currentPath = "";
473 for (int i = 0; i < pathSteps.length; i++) {
474 if (!pathSteps[i].isEmpty()) {
475 currentPath += "/" + pathSteps[i];
476 Element pathStepDescription = getGroupDescription(pathSteps[i]);
477 if (pathStepDescription != null){
478 pathStepDescription.setAttribute(GSXML.POSITION_ATT, String.valueOf(i));
479 pathStepDescription.setAttribute(GSXML.PATH_ATT, currentPath);
480 }
[31285]481 pathInfo.appendChild(doc.importNode(pathStepDescription, true));
[31166]482 }
483 }
484
485 return pathInfo;
486 }
[31285]487 private Element getAvailableCollectionList(UserContext userContext){
[31181]488 Document doc = XMLConverter.newDOM();
489 // Get the message router info
[32115]490 Element inforesponseMessage = new Request(doc, userContext, router, GSXML.REQUEST_TYPE_DESCRIBE).send();
491 if (inforesponseMessage == null) {
[31181]492 logger.error(" couldn't query the message router!");
493 return null;
494 }
[32115]495 Element mr_info_response = (Element) GSXML.getChildByTagName(inforesponseMessage, GSXML.RESPONSE_ELEM);
[31181]496 if (mr_info_response == null) {
497 logger.error("Message router response is null!");
498 return null;
499 }
500
501 Element mr_collection_list = (Element) GSXML.getChildByTagName(mr_info_response, GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
502
503 return mr_collection_list;
504 }
[31285]505 private Element getSearchableCollectionList(UserContext userContext){
506 Document doc = XMLConverter.newDOM();
507 Element collectionList = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
508 // Get the message router info
509 Element mr_info_message = doc.createElement(GSXML.MESSAGE_ELEM);
510 Element mr_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_DESCRIBE, "TextQuery" , userContext);
511 mr_info_message.appendChild(mr_request);
512 Element mr_info_response_message = (Element) this.router.process(mr_info_message);
513 if (mr_info_response_message == null) {
514 logger.error(" couldn't query the message router!");
515 return null;
516 }
517 NodeList options = mr_info_response_message.getElementsByTagName(GSXML.PARAM_OPTION_ELEM);
518 for (int i = 0; i < options.getLength(); i++) {
519 Element option = (Element) options.item(i);
520 String name = option.getAttribute(GSXML.NAME_ATT);
521 if (name.equals("all")){
522 continue;
523 }
524 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
525 collection.setAttribute(GSXML.NAME_ATT, name);
526 collectionList.appendChild(collection);
527 }
528 return collectionList;
529 }
[30540]530}
Note: See TracBrowser for help on using the repository browser.