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

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

Safe read from group config file

File size: 19.7 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 private static final String GROUP_CONTENT = "GroupCurrentContent";
32 private static final String UNIQUE_COLLECTIONS = "UniqueCollections";
33 private 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 Element groupContent = getRawCurrentContent(groups[i]);
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
231 protected Element processCollectionsHierarchy(Element request){
232
233 Document doc = XMLConverter.newDOM();
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 }
246
247 //Get ungrouped collection list
248 sanitizeCurrentContent(currentContent, searchableCollectionList);
249 addGroupInfo(currentContent, currentPath);
250 addUngroupedCollections(currentContent, searchableCollectionList);
251 addAllOption(currentContent);
252 result.appendChild(doc.importNode(currentContent, true));
253 return result;
254 }
255
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
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);
280 String title;
281 if (titleEl != null) {
282 title = titleEl.getTextContent();
283 } else {
284 title = name;
285 }
286 group.setAttribute(GSXML.TITLE_ELEM, title );
287 addGroupInfo(group, newPath);
288 }
289
290 }
291
292 private Element getRawCurrentContent(String path) {
293
294 if (path == null) {
295 path = "";
296 }
297
298 Document doc = XMLConverter.newDOM();
299 path = path.replaceAll("(/+)", "/");
300 path = path.replaceAll("(^/+)|(/+$)", "");
301
302 String[] pathSteps = path.split("/");
303
304
305 Element currentContent = (Element) hierarchy.cloneNode(true);
306 // Get the current view
307 for (int i = 0; i < pathSteps.length; i++) {
308 if (!pathSteps[i].isEmpty()) {
309 currentContent = GSXML.getNamedElement(currentContent, GSXML.GROUP_ELEM, GSXML.NAME_ATT, pathSteps[i]);
310 if (currentContent == null){
311 break;
312 }
313 }
314 }
315 if (currentContent == null || !currentContent.hasChildNodes()) {
316 // Return to the main page
317 return null;
318 }
319 return currentContent;
320 }
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 }
356
357 private boolean readGroupConfiguration() {
358
359 File configFile = new File(GSFile.groupConfigFile(site_home));
360 //
361 if (!configFile.exists()) {
362 logger.info("Groups config file " + configFile.getPath() + " does not exist.");
363 return false;
364 }
365 Document doc;
366 Element content;
367 try {
368 doc = XMLConverter.getDOM(configFile);
369 content = doc.getDocumentElement();
370 } catch (Exception e) {
371 System.out.println(e.getClass());
372 e.printStackTrace();
373 return false;
374 }
375 // XPath to find empty text nodes.
376 try {
377 XPathFactory xpathFactory = XPathFactory.newInstance();
378 XPathExpression xpathExp = xpathFactory.newXPath().compile("//text()[normalize-space(.) = '']");
379 NodeList emptyTextNodes = (NodeList) xpathExp.evaluate(doc, XPathConstants.NODESET);
380 for (int i = 0; i < emptyTextNodes.getLength(); i++) {
381 Node emptyTextNode = emptyTextNodes.item(i);
382 emptyTextNode.getParentNode().removeChild(emptyTextNode);
383 }
384
385 } catch (XPathExpressionException e) {
386 logger.error("Error occurred while trying to remove emtpy nodes from groupConfig.xml");
387 e.printStackTrace();
388 return false;
389 }
390
391 hierarchy = (Element) GSXML.getChildByTagName(content, GSXML.HIERARCHY_ELEM);
392 groupDesc = (Element) GSXML.getChildByTagName(content, GSXML.GROUP_DESC_ELEM);
393 if (hierarchy == null || groupDesc == null){
394 logger.error("Error processing groups configuration. <groupConfig> should have both <hierarchy> and <groupDescriptions> elements. Check groupConfig.xml");
395 return false;
396 }
397 verifyGroupDescription();
398 return true;
399 }
400
401 private void verifyGroupDescription() {
402 Document doc = groupDesc.getOwnerDocument();
403 NodeList groups = hierarchy.getElementsByTagName(GSXML.GROUP_ELEM);
404 for (int i = 0; i < groups.getLength(); i++) {
405 Element group = (Element) groups.item(i);
406 String name = group.getAttribute(GSXML.NAME_ATT);
407 Element foundDescription = GSXML.getNamedElement(groupDesc, GSXML.GROUP_ELEM, GSXML.NAME_ATT, name);
408 if (foundDescription == null){
409 Element defaultDescription = doc.createElement(GSXML.GROUP_ELEM);
410 defaultDescription.setAttribute(GSXML.NAME_ATT, name);
411 Element groupTitle = doc.createElement(GSXML.TITLE_ELEM);
412 groupTitle.setTextContent(name);
413 defaultDescription.appendChild(groupTitle);
414 groupDesc.appendChild(defaultDescription);
415 }
416 }
417
418 }
419
420 private Element getGroupDescription(String name) {
421 Element description = (Element) GSXML.getNamedElement(groupDesc, GSXML.GROUP_ELEM, GSXML.NAME_ATT, name);
422 if (description == null) {
423 logger.error("GroupDescription is not defined. Check your groupConfig.xml");
424 }
425 return description;
426 }
427
428 private Element getUngroupedCollections(Element mr_collection_list) {
429
430 Document doc = XMLConverter.newDOM();
431 // Create Set
432 Set<String> hierarchy_unique_collections = new HashSet<String>();
433 // Element hierarchyCollections = doc.createElement("coll_list");
434 // Get collection nodes
435
436 NodeList hierarchy_all_collection_list = hierarchy.getElementsByTagName(GSXML.COLLECTION_ELEM);
437 // Save hierarchy collection names to Hashset
438 for (int i = 0; i < hierarchy_all_collection_list.getLength(); i++) {
439 Element collection_element = (Element) hierarchy_all_collection_list.item(i);
440 hierarchy_unique_collections.add(collection_element.getAttribute(GSXML.NAME_ATT));
441 }
442 // Save available by message router collection names to Hashset
443 Set<String> mr_collections = new HashSet<String>();
444 NodeList mr_coll_list = mr_collection_list.getElementsByTagName(GSXML.COLLECTION_ELEM);
445
446 for (int i = 0; i < mr_coll_list.getLength(); i++) {
447 Element collection_element = (Element) mr_coll_list.item(i);
448 mr_collections.add(collection_element.getAttribute(GSXML.NAME_ATT));
449 }
450 //Save collections available by message router and not existed in hierarchy to ungrouped collections set
451 Set<String> ungrouped_collections = new HashSet<String>();
452 for (String string : mr_collections) {
453 if (!hierarchy_unique_collections.contains(string)){
454 ungrouped_collections.add(string);
455 }
456 }
457 //Output
458 Element result = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
459 for (String name : ungrouped_collections) {
460 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
461 collection.setAttribute(GSXML.NAME_ATT, name);
462 result.appendChild(collection);
463 }
464 return result;
465
466 }
467 private Element getPathInfo(String path) {
468
469 Document doc = XMLConverter.newDOM();
470
471 if (path == null) {
472 path = "";
473 }
474 String[] pathSteps = path.split("/");
475
476 Element pathInfo = doc.createElement(GSXML.PATH_ELEM + GSXML.LIST_MODIFIER);
477
478 String currentPath = "";
479 for (int i = 0; i < pathSteps.length; i++) {
480 if (!pathSteps[i].isEmpty()) {
481 currentPath += "/" + pathSteps[i];
482 Element pathStepDescription = getGroupDescription(pathSteps[i]);
483 if (pathStepDescription != null){
484 pathStepDescription.setAttribute(GSXML.POSITION_ATT, String.valueOf(i));
485 pathStepDescription.setAttribute(GSXML.PATH_ATT, currentPath);
486 }
487 pathInfo.appendChild(doc.importNode(pathStepDescription, true));
488 }
489 }
490
491 return pathInfo;
492 }
493 private Element getAvailableCollectionList(UserContext userContext){
494 Document doc = XMLConverter.newDOM();
495 // Get the message router info
496 Element inforesponseMessage = new Request(doc, userContext, router, GSXML.REQUEST_TYPE_DESCRIBE).send();
497 if (inforesponseMessage == null) {
498 logger.error(" couldn't query the message router!");
499 return null;
500 }
501 Element mr_info_response = (Element) GSXML.getChildByTagName(inforesponseMessage, GSXML.RESPONSE_ELEM);
502 if (mr_info_response == null) {
503 logger.error("Message router response is null!");
504 return null;
505 }
506
507 Element mr_collection_list = (Element) GSXML.getChildByTagName(mr_info_response, GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
508
509 return mr_collection_list;
510 }
511 private Element getSearchableCollectionList(UserContext userContext){
512 Document doc = XMLConverter.newDOM();
513 Element collectionList = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
514 // Get the message router info
515 Element mr_info_message = doc.createElement(GSXML.MESSAGE_ELEM);
516 Element mr_request = GSXML.createBasicRequest(doc, GSXML.REQUEST_TYPE_DESCRIBE, "TextQuery" , userContext);
517 mr_info_message.appendChild(mr_request);
518 Element mr_info_response_message = (Element) this.router.process(mr_info_message);
519 if (mr_info_response_message == null) {
520 logger.error(" couldn't query the message router!");
521 return null;
522 }
523 NodeList options = mr_info_response_message.getElementsByTagName(GSXML.PARAM_OPTION_ELEM);
524 for (int i = 0; i < options.getLength(); i++) {
525 Element option = (Element) options.item(i);
526 String name = option.getAttribute(GSXML.NAME_ATT);
527 if (name.equals("all")){
528 continue;
529 }
530 Element collection = doc.createElement(GSXML.COLLECTION_ELEM);
531 collection.setAttribute(GSXML.NAME_ATT, name);
532 collectionList.appendChild(collection);
533 }
534 return collectionList;
535 }
536}
Note: See TracBrowser for help on using the repository browser.