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

Last change on this file since 31285 was 31285, checked in by Georgiy Litvinov, 7 years ago

Java code for hierarchy view in cross collection search

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