001 /*
002 * $RCSfile: MCRClassificationBrowserData.java,v $
003 * $Revision: 15422 $ $Date: 2009-07-01 10:48:51 +0200 (Wed, 01 Jul 2009) $
004 *
005 * This file is part of *** M y C o R e ***
006 * See http://www.mycore.de/ for details.
007 *
008 * This program is free software; you can use it, redistribute it
009 * and / or modify it under the terms of the GNU General Public License
010 * (GPL) as published by the Free Software Foundation; either version 2
011 * of the License or (at your option) any later version.
012 *
013 * This program is distributed in the hope that it will be useful, but
014 * WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program, in a file called gpl.txt or license.txt.
020 * If not, write to the Free Software Foundation Inc.,
021 * 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
022 */
023
024 package org.mycore.datamodel.classifications;
025
026 import java.util.ArrayList;
027 import java.util.Collection;
028 import java.util.Hashtable;
029 import java.util.Iterator;
030 import java.util.List;
031 import java.util.Map;
032
033 import org.apache.log4j.Logger;
034 import org.jdom.Document;
035 import org.jdom.Element;
036 import org.jdom.Namespace;
037 import org.jdom.xpath.XPath;
038 import org.mycore.access.MCRAccessManager;
039 import org.mycore.common.MCRConfiguration;
040 import org.mycore.common.MCRSession;
041 import org.mycore.common.MCRSessionMgr;
042 import org.mycore.common.events.MCRSessionEvent;
043 import org.mycore.common.events.MCRSessionListener;
044 import org.mycore.datamodel.classifications2.MCRCategLinkServiceFactory;
045 import org.mycore.datamodel.classifications2.MCRCategory;
046 import org.mycore.datamodel.classifications2.MCRCategoryID;
047 import org.mycore.datamodel.classifications2.MCRLabel;
048
049 /**
050 * Instances of MCRClassificationBrowser contain the data of the currently
051 * displayed navigation tree. MCRClassificationBrowser uses one
052 * MCRClassificationBrowserData instance per browser session to store and update
053 * the category lines to be displayed.
054 *
055 * @author Anja Schaar
056 *
057 */
058 public class MCRClassificationBrowserData {
059
060 protected String pageName;
061
062 protected String xslStyle;
063
064 protected String uri;
065
066 private static MCRConfiguration config;
067
068 private static final Logger LOGGER = Logger.getLogger(MCRClassificationBrowserData.class);
069
070 private ArrayList<Element> lines;
071
072 private MCRCategory classif;
073
074 private String startPath = "";
075
076 private String actItemID = "";
077
078 private String lastItemID = "";
079
080 private String[] categFields;
081
082 private String emptyLeafs = null;
083
084 private String view = null;
085
086 private boolean comments = false;
087
088 private String searchField = "";
089
090 private boolean sort = false;
091
092 private String objectType = null;
093
094 private String[] objectTypeArray = null;
095
096 private String restriction = null;
097
098 int maxlevel = 0;
099
100 int totalNumOfDocs = 0;
101
102 public static Map<String, String> ClassUserTable = new Hashtable<String, String>();
103
104 private static MCRSessionListener ClassUserTableCleaner = new MCRSessionListener() {
105
106 public void sessionEvent(MCRSessionEvent event) {
107 switch (event.getType()) {
108 case destroyed:
109 clearUserClassTable(event.getSession());
110 break;
111 default:
112 LOGGER.debug("Skipping event: " + event.getType());
113 break;
114 }
115 }
116
117 };
118
119 static {
120 MCRSessionMgr.addSessionListener(ClassUserTableCleaner);
121 }
122
123 public MCRClassificationBrowserData(final String u, final String mode, final String actclid, final String actEditorCategid)
124 throws Exception {
125 uri = u;
126 config = MCRConfiguration.instance();
127 LOGGER.debug(" incomming Path " + uri);
128
129 final String[] uriParts = uri.split("/"); // mySplit();
130 LOGGER.info(" Start");
131 String classifID = null;
132 final String browserClass = (uriParts.length <= 1 ? "default" : uriParts[1]);
133 LOGGER.debug(" PathParts - classification " + browserClass);
134 LOGGER.debug(" Number of PathParts =" + uriParts.length);
135 try {
136 classifID = config.getString("MCR.ClassificationBrowser." + browserClass + ".Classification");
137 } catch (final org.mycore.common.MCRConfigurationException noClass) {
138 classifID = actclid;
139 }
140 try {
141 pageName = config.getString("MCR.ClassificationBrowser." + browserClass + ".EmbeddingPage");
142 } catch (final org.mycore.common.MCRConfigurationException noPagename) {
143 pageName = config.getString("MCR.ClassificationBrowser.default.EmbeddingPage");
144 }
145 try {
146 xslStyle = config.getString("MCR.ClassificationBrowser." + browserClass + ".Style");
147 } catch (final org.mycore.common.MCRConfigurationException noStyle) {
148 xslStyle = config.getString("MCR.ClassificationBrowser.default.Style");
149 }
150 try {
151 searchField = config.getString("MCR.ClassificationBrowser." + browserClass + ".searchField");
152 } catch (final org.mycore.common.MCRConfigurationException noSearchfield) {
153 searchField = config.getString("MCR.ClassificationBrowser.default.searchField");
154 }
155
156 try {
157 emptyLeafs = config.getString("MCR.ClassificationBrowser." + browserClass + ".EmptyLeafs");
158 } catch (final org.mycore.common.MCRConfigurationException noEmptyLeafs) {
159 emptyLeafs = config.getString("MCR.ClassificationBrowser.default.EmptyLeafs");
160 }
161 try {
162 view = config.getString("MCR.ClassificationBrowser." + browserClass + ".View");
163 } catch (final org.mycore.common.MCRConfigurationException noView) {
164 view = config.getString("MCR.ClassificationBrowser.default.View");
165 }
166 setObjectTypes(browserClass);
167
168 sort = config.getBoolean("MCR.ClassificationBrowser." + browserClass + ".Sort", false);
169 comments = config.getBoolean("MCR.ClassificationBrowser." + browserClass + ".Comments", false);
170 restriction = config.getString("MCR.ClassificationBrowser." + browserClass + ".Restriction", null);
171
172 startPath = browserClass;
173
174 if ("edit".equals(mode)) {
175 pageName = config.getString("MCR.classeditor.EmbeddingPage");
176 xslStyle = config.getString("MCR.classeditor.Style");
177 sort = false;
178 view = "tree";
179
180 if (classifID.length() == 0) {
181 return;
182 }
183 }
184
185 if (emptyLeafs == null) {
186 emptyLeafs = "yes";
187 }
188 if (view == null || !view.endsWith("flat")) {
189 view = "tree";
190 }
191 LOGGER.info("uriParts length: " + uriParts.length);
192 clearPath(uriParts);
193 MCRCategoryID id = MCRCategoryID.rootID(classifID);
194 setClassification(id);
195 setActualPath(actEditorCategid);
196
197 if (LOGGER.isDebugEnabled()) {
198 LOGGER.debug(" SetClassification " + classifID);
199 LOGGER.debug(" Empty nodes: " + emptyLeafs);
200 LOGGER.debug(" View: " + view);
201 LOGGER.debug(" Comment: " + comments);
202 LOGGER.debug(" Doctypes: " + objectType);
203 for (String element : objectTypeArray) {
204 LOGGER.debug(" Type: " + element);
205 }
206 LOGGER.debug(" Restriction: " + restriction);
207 LOGGER.debug(" Sort: " + sort);
208 }
209 }
210
211 private void setObjectTypes(final String browserClass) {
212 LOGGER.debug("setObjectTypes(" + browserClass + ")");
213 try {
214 // NOTE: read *.Doctype for compatiblity reasons
215 objectType = config.getString("MCR.ClassificationBrowser." + browserClass + ".Objecttype", config.getString(
216 "MCR.ClassificationBrowser." + browserClass + ".Doctype", null));
217 } catch (final org.mycore.common.MCRConfigurationException noDoctype) {
218 objectType = config.getString("MCR.ClassificationBrowser.default.ObjectType", config
219 .getString("MCR.ClassificationBrowser.default.Doctype"));
220 }
221
222 if (objectType != null) {
223 objectTypeArray = objectType.split(",");
224 } else {
225 objectTypeArray = new String[0];
226 }
227 }
228
229 public String getUri() {
230 return uri;
231 }
232
233 /**
234 * Returns true if category comments for the classification currently
235 * displayed should be shown.
236 */
237 public boolean showComments() {
238 return comments;
239 }
240
241 /**
242 * Returns the pageName for the classification
243 */
244 public String getPageName() {
245 return pageName;
246 }
247
248 /**
249 * Returns the xslStyle for the classification
250 */
251 public String getXslStyle() {
252 return xslStyle;
253 }
254
255 public MCRCategory getClassification() {
256 return classif;
257 }
258
259 @SuppressWarnings("unchecked")
260 public org.jdom.Document loadTreeIntoSite(final org.jdom.Document cover, final org.jdom.Document browser) {
261 final Element placeholder = cover.getRootElement().getChild("classificationBrowser");
262 LOGGER.info(" Found Entry at " + placeholder);
263 if (placeholder != null) {
264 final List<Element> children = browser.getRootElement().getChildren();
265 for (Element child : children) {
266 placeholder.addContent((Element) child.clone());
267 }
268 }
269 LOGGER.debug(cover);
270 return cover;
271 }
272
273 public final void setClassification(final MCRCategoryID classifID) throws Exception {
274 classif = getClassificationPool().getClassificationAsPojo(classifID, true);
275 if (classif == null)
276 return;
277 lines = new ArrayList<Element>();
278 totalNumOfDocs = 0;
279 putCategoriesintoLines(-1, classif.getChildren());
280 LOGGER.debug("Arraylist of CategItems initialized - Size " + lines.size());
281 }
282
283 private void clearPath(final String[] uriParts) throws Exception {
284 final String[] cati = new String[uriParts.length];
285 String path = "";
286 if (uriParts.length == 1) {
287 path = "/" + uriParts[0];
288 } else {
289 path = "/" + uriParts[1];
290 }
291 int len = 0;
292 // pfad bereinigen
293 for (int k = 2; k < uriParts.length; k++) {
294 LOGGER.debug(" uriParts[k]=" + uriParts[k] + " k=" + k);
295 if (uriParts[k].length() > 0) {
296 if (uriParts[k].equalsIgnoreCase("..") && len > 0) {
297 len--;
298 } else {
299 cati[len] = uriParts[k];
300 len++;
301 }
302 }
303 }
304
305 // remove double entries from path
306 // (if an entry appears the 2nd time it will not be displayed -> so we
307 // can remove it here)
308 final ArrayList<String> result = new ArrayList<String>();
309 for (int i = 0; i < len; i++) {
310 final String x = cati[i];
311 if (result.contains(x)) {
312 result.remove(x);
313 } else {
314 result.add(x);
315 }
316 }
317
318 // reinitialisieren
319 categFields = new String[result.size()];
320 int j = 0;
321 for (String uriPart : result) {
322 categFields[j] = uriPart;
323 j++;
324 path += "/" + uriPart;
325 }
326 this.uri = path;
327 }
328
329 private void setActualPath(final String actEditorCategid) throws Exception {
330 actItemID = lastItemID = "";
331
332 for (String categID : categFields) {
333 update(categID);
334 lastItemID = actItemID;
335 actItemID = categID;
336 }
337 if (actEditorCategid != null) {
338 actItemID = lastItemID = actEditorCategid;
339 }
340 }
341
342 private Element setTreeline(MCRCategory categ) {
343 Element categElement = MCRCategoryElementFactory.getCategoryElement(categ, false, 0);
344 categElement.setAttribute("level", String.valueOf(categ.getLevel() + 1));
345
346 if (categ.hasChildren()) {
347 categElement.setAttribute("hasChildren", "T");
348 } else {
349 categElement.setAttribute("hasChildren", " ");
350 }
351 return categElement;
352 }
353
354 private Element getTreeline(final int i) {
355 if (i >= lines.size()) {
356 return null;
357 }
358 return lines.get(i);
359 }
360
361 private void putCategoriesintoLines(final int startpos, final List<MCRCategory> children) {
362 LOGGER.debug("Start Explore Arraylist of CategItems ");
363 int i = startpos;
364 List<MCRCategoryID> ids = new ArrayList<MCRCategoryID>();
365
366 for (MCRCategory cat : children) {
367 ids.add(cat.getId());
368 }
369
370 for (MCRCategory cat : children) {
371 lines.add(++i, setTreeline(cat));
372 }
373 LOGGER.debug("End Explore - Arraylist of CategItems ");
374 }
375
376 public org.jdom.Document createXmlTreeforAllClassifications() throws Exception {
377 LOGGER.debug("create XML tree for all classifications");
378 final Element xDocument = new Element("classificationbrowse");
379 final Element CreateClassButton = new Element("userCanCreate");
380 if (MCRAccessManager.checkPermission("create-classification")) {
381 CreateClassButton.addContent("true");
382 } else {
383 CreateClassButton.addContent("false");
384 }
385
386 xDocument.addContent(CreateClassButton);
387
388 final Element xNavtree = new Element("classificationlist");
389 xDocument.addContent(xNavtree);
390 String browserClass = "";
391
392 LOGGER.debug("query classification links");
393 MCRClassificationPool classificationPool = getClassificationPool();
394 for (MCRCategoryID classID : classificationPool.getAllIDs()) {
395 MCRCategory classif = classificationPool.getClassificationAsPojo(classID, false);
396 LOGGER.debug("get classification " + classID);
397 LOGGER.debug("get browse element");
398 Element cli = getBrowseElement(classif);
399 LOGGER.debug("get browse element ... done");
400 String sessionID = MCRSessionMgr.getCurrentSession().getID();
401 // set browser type
402 try {
403 browserClass = config.getString("MCR.classeditor." + classif.getId().getRootID());
404 } catch (final Exception ignore) {
405 browserClass = "default";
406 }
407 // set permissions
408 if (classificationPool.isEdited(classID)) {
409 cli.setAttribute("edited", "true");
410 cli.setAttribute("userCanEdit", "false");
411 cli.setAttribute("userCanDelete", "false");
412 } else {
413 cli.setAttribute("edited", "false");
414 if (MCRAccessManager.checkPermission(classID.getRootID(), "writedb")) {
415 cli.setAttribute("userCanEdit", "true");
416 } else {
417 cli.setAttribute("userCanEdit", "false");
418 }
419 final boolean mayDelete = MCRAccessManager.checkPermission(classID.getRootID(), "deletedb");
420 if (mayDelete) {
421 cli.setAttribute("userCanDelete", "true");
422 LOGGER.debug("counting linked objects");
423 boolean hasLinks = MCRCategLinkServiceFactory.getInstance().hasLinks(classif).get(classID).booleanValue();
424 LOGGER.debug("counting linked objects ... done");
425 cli.setAttribute("hasLinks", String.valueOf(hasLinks));
426 } else {
427 cli.setAttribute("userCanDelete", "false");
428 }
429 }
430 // set done flag
431 if (ClassUserTable.containsKey(classID.getRootID())) {
432 if (ClassUserTable.get(classID.getRootID()) != sessionID) {
433 MCRSession oldsession = MCRSessionMgr.getSession(ClassUserTable.get(classID.getRootID()));
434 if (null != oldsession)
435 cli.setAttribute("userEdited", oldsession.getCurrentUserID());
436 else {
437 ClassUserTable.remove(classID.getRootID());
438 cli.setAttribute("userEdited", "false");
439 }
440 } else {
441 cli.setAttribute("userEdited", "false");
442 }
443 } else {
444 cli.setAttribute("userEdited", "false");
445 }
446
447 cli.setAttribute("browserClass", browserClass);
448 setObjectTypes(browserClass);
449 xNavtree.addContent(cli);
450 }
451 return new Document(xDocument);
452 }
453
454 private static Element getBrowseElement(MCRCategory classif) {
455 Element ce = new Element("classification");
456 ce.setAttribute("ID", classif.getId().getRootID());
457 for (MCRLabel label : classif.getLabels()) {
458 Element labelElement = new Element("label");
459 if (label.getLang() != null) {
460 labelElement.setAttribute("lang", label.getLang(), Namespace.XML_NAMESPACE);
461 }
462 if (label.getText() != null) {
463 labelElement.setAttribute("text", label.getText());
464 }
465 if (label.getDescription() != null) {
466 labelElement.setAttribute("description", label.getDescription());
467 }
468 ce.addContent(labelElement);
469 }
470 return ce;
471 }
472
473 /**
474 * Creates an XML representation of MCRClassificationBrowserData
475 *
476 * @author Anja Schaar
477 *
478 */
479
480 public org.jdom.Document createXmlTree(final String lang) throws Exception {
481
482 LOGGER.debug("Show tree for classification:" + classif.getId());
483 final MCRCategory cl = getClassificationPool().getClassificationAsPojo(classif.getId(), true);
484 LOGGER.debug("Got classification");
485 MCRClassificationPool cp = getClassificationPool();
486 MCRLabel labels = getLabel(cl, lang);
487 Element xDocument = new Element("classificationBrowse");
488
489 final Element xID = new Element("classifID");
490 xID.addContent(cl.getId().getRootID());
491 xDocument.addContent(xID);
492
493 final Element xUserEdited = new Element("userEdited");
494 if (ClassUserTable.containsKey(cl.getId().getRootID())) {
495 xUserEdited.addContent(MCRSessionMgr.getSession(ClassUserTable.get(cl.getId().getRootID())).getCurrentUserID());
496 } else {
497 xUserEdited.addContent("false");
498 }
499 xDocument.addContent(xUserEdited);
500
501 final Element xSessionID = new Element("session");
502 if (ClassUserTable.containsKey(cl.getId().getRootID())) {
503 xSessionID.addContent(ClassUserTable.get(cl.getId().getRootID()));
504 } else {
505 xSessionID.addContent("");
506 }
507
508 xDocument.addContent(xSessionID);
509
510 final Element xCurrentSessionID = new Element("currentSession");
511 xCurrentSessionID.addContent(MCRSessionMgr.getCurrentSession().getID());
512 xDocument.addContent(xCurrentSessionID);
513
514 final Element xLabel = new Element("label");
515 xLabel.addContent(labels.getText());
516 xDocument.addContent(xLabel);
517
518 final Element xDesc = new Element("description");
519 xDesc.addContent(labels.getDescription());
520 xDocument.addContent(xDesc);
521
522 final Element xDocuments = new Element("cntDocuments");
523 xDocuments.addContent(String.valueOf(totalNumOfDocs));
524 xDocument.addContent(xDocuments);
525
526 final Element xShowComments = new Element("showComments");
527 xShowComments.addContent(String.valueOf(showComments()));
528 xDocument.addContent(xShowComments);
529
530 final Element xUri = new Element("uri");
531 xUri.addContent(uri);
532 xDocument.addContent(xUri);
533
534 final Element xStartPath = new Element("startPath");
535 xStartPath.addContent(startPath);
536 xDocument.addContent(xStartPath);
537
538 final Element xSearchField = new Element("searchField");
539 xSearchField.addContent(searchField);
540 xDocument.addContent(xSearchField);
541
542 // add edit button if user has permission
543 final Element CreateButton = new Element("userCanCreate");
544 final Element EditButton = new Element("userCanEdit");
545 final Element DeleteButton = new Element("userCanDelete");
546 LOGGER.debug("now we check this right for the current user");
547 // now we check this right for the current user
548 if (cp.isEdited(getClassification().getId()) == false) {
549 String permString = String.valueOf(MCRAccessManager.checkPermission("create-classification"));
550 CreateButton.addContent(permString);
551 xDocument.addContent(CreateButton);
552 permString = String.valueOf(MCRAccessManager.checkPermission(cl.getId().getRootID(), "writedb"));
553 EditButton.addContent(permString);
554 xDocument.addContent(EditButton);
555 permString = String.valueOf(MCRAccessManager.checkPermission(cl.getId().getRootID(), "deletedb"));
556 DeleteButton.addContent(permString);
557 xDocument.addContent(DeleteButton);
558 } else {
559 String permString = "true";
560 CreateButton.addContent(permString);
561 xDocument.addContent(CreateButton);
562 EditButton.addContent(permString);
563 xDocument.addContent(EditButton);
564 DeleteButton.addContent(permString);
565 xDocument.addContent(DeleteButton);
566 }
567
568 // data as XML from outputNavigationTree
569 final Element xNavtree = new Element("navigationtree");
570 xNavtree.setAttribute("classifID", cl.getId().getRootID());
571 xNavtree.setAttribute("categID", actItemID);
572 xNavtree.setAttribute("predecessor", lastItemID);
573 xNavtree.setAttribute("emptyLeafs", emptyLeafs);
574 xNavtree.setAttribute("view", view);
575 final StringBuffer sb = new StringBuffer();
576 if (objectTypeArray.length > 1) {
577 sb.append("(");
578 }
579 for (int i = 0; i < objectTypeArray.length; i++) {
580 sb.append("(objectType+=+").append(objectTypeArray[i]).append(")");
581 if ((objectTypeArray.length > 1) && (i < objectTypeArray.length - 1)) {
582 sb.append("+or+");
583 }
584 }
585 if (objectTypeArray.length > 1) {
586 sb.append(")");
587 }
588 xNavtree.setAttribute("doctype", sb.toString());
589 xNavtree.setAttribute("restriction", restriction != null ? restriction : "");
590 xNavtree.setAttribute("searchField", searchField);
591
592 int i = 0;
593 Element line;
594 List<MCRCategoryID> ids = new ArrayList<MCRCategoryID>();
595 LOGGER.debug("process tree lines: fetch ids");
596 while ((line = getTreeline(i++)) != null) {
597 final String catid = line.getAttributeValue("ID");
598 ids.add(new MCRCategoryID(cl.getId().getRootID(), catid));
599 }
600 i = 0;
601 LOGGER.debug("fetch Map<MCRCategoryID,Boolean>");
602 Map<MCRCategoryID, Boolean> countMap = MCRCategLinkServiceFactory.getInstance().hasLinks(getClassification());
603 LOGGER.debug("process tree lines: build xml tree");
604 while ((line = getTreeline(i++)) != null) {
605
606 final String catid = line.getAttributeValue("ID");
607 final Boolean hasLinkValue = countMap.get(new MCRCategoryID(cl.getId().getRootID(), catid));
608 //new categories are not yet in countMap
609 boolean hasLinks = hasLinkValue != null ? hasLinkValue.booleanValue() : false;
610 final String status = line.getAttributeValue("hasChildren");
611
612 Element label = (Element) XPath.selectSingleNode(line, "label[lang('" + lang + "')]");
613 if (label == null) {
614 label = (Element) XPath.selectSingleNode(line, "label[lang('"
615 + MCRConfiguration.instance().getString("MCR.Metadata.DefaultLang", "en") + "')]");
616 }
617 if (label == null) {
618 label = (Element) XPath.selectSingleNode(line, "label");
619 }
620 final String text = label.getAttributeValue("text");
621 final String description = label.getAttributeValue("description");
622
623 final int level = Integer.parseInt(line.getAttributeValue("level"));
624
625 if (emptyLeafs.endsWith("no") && !hasLinks) {
626 LOGGER.debug(" empty Leaf continue - " + emptyLeafs);
627 continue;
628 }
629 final Element xRow = new Element("row");
630 final Element xCol1 = new Element("col");
631 final Element xCol2 = new Element("col");
632
633 xRow.addContent(xCol1);
634 xRow.addContent(xCol2);
635 xNavtree.addContent(xRow);
636
637 xCol1.setAttribute("lineLevel", String.valueOf(level - 1));
638 xCol1.setAttribute("childpos", "middle");
639
640 if (level > maxlevel) {
641 xCol1.setAttribute("childpos", "first");
642 maxlevel = level;
643 if (getTreeline(i) == null) {
644 // Spezialfall nur genau ein Element
645 xCol1.setAttribute("childpos", "firstlast");
646 }
647 } else if (getTreeline(i) == null) {
648 xCol1.setAttribute("childpos", "last");
649 }
650
651 xCol1.setAttribute("folder1", "folder_plain");
652 xCol1.setAttribute("folder2", hasLinks ? "folder_closed_in_use" : "folder_closed_empty");
653
654 if (status.equals("T")) {
655 xCol1.setAttribute("plusminusbase", catid);
656 xCol1.setAttribute("folder1", "folder_plus");
657 } else if (status.equals("F")) {
658 xCol1.setAttribute("plusminusbase", catid);
659 xCol1.setAttribute("folder1", "folder_minus");
660 xCol1.setAttribute("folder2", hasLinks ? "folder_open_in_use" : "folder_open_empty");
661 }
662
663 String search = uri;
664 search += "/" + catid;
665
666 if (search.indexOf("//") > 0)
667 search = search.substring(0, search.indexOf("//")) + search.substring(search.indexOf("//") + 1);
668
669 xCol2.setAttribute("searchbase", search);
670 xCol2.setAttribute("lineID", catid);
671 xCol2.setAttribute("hasLinks", String.valueOf(hasLinks));
672
673 xCol2.addContent(text);
674
675 if (showComments() && (description != null)) {
676 final Element comment = new Element("comment");
677 xCol2.addContent(comment);
678 comment.setText(description);
679 }
680 }
681 LOGGER.debug("Building XML document");
682
683 xNavtree.setAttribute("rowcount", "" + i);
684 xDocument.addContent(xNavtree);
685
686 if ("true".equals(sort)) {
687 xDocument = sortMyTree(xDocument);
688 }
689 Document doc = new org.jdom.Document(xDocument);
690 //MCRUtils.writeJDOMToSysout(doc);
691 return doc;
692 }
693
694 public void update(final String categID) throws Exception {
695 int lastLevel = 0;
696 boolean hideLevel = false;
697
698 MCRCategory parent = MCRClassificationBrowserData.getClassificationPool().getClassificationAsPojo(classif.getId(), true);
699 MCRCategory cat = findCategory(parent, categID);
700
701 LOGGER.debug(" update CategoryTree for: " + categID);
702 Element line;
703 for (int i = 0; i < lines.size(); i++) {
704 line = getTreeline(i);
705 final String catid = line.getAttributeValue("ID");
706 final String status = line.getAttributeValue("hasChildren");
707 final int level = Integer.parseInt(line.getAttributeValue("level"));
708
709 hideLevel = hideLevel && (level > lastLevel);
710 LOGGER.debug(" compare CategoryTree on " + i + "_" + catid + " to " + categID);
711 if (view.endsWith("tree")) {
712 if (hideLevel) {
713 lines.remove(i--);
714 } else if (categID.equals(catid)) {
715 if (status.equals("F")) // hide expanded category - //
716 // children
717 {
718 line.setAttribute("hasChildren", "T");
719 hideLevel = true;
720 lastLevel = level;
721 } else if (status.equals("T")) // expand category - //
722 // children
723 {
724 line.setAttribute("hasChildren", "F");
725 putCategoriesintoLines(i, cat.getChildren());
726 }
727 }
728 } else {
729 if (categID.equalsIgnoreCase(catid)) {
730 line.setAttribute("level", "0");
731 LOGGER.info(" expand " + catid);
732 line.setAttribute("hasChildren", "F");
733 putCategoriesintoLines(i, cat.getChildren());
734 } else {
735 LOGGER.debug(" remove lines " + i + "_" + catid);
736 lines.remove(i--);
737 }
738 }
739
740 }
741 }
742
743 // don't use it works not really good
744
745 private final Element sortMyTree(final Element xDocument) {
746 Element xDoc = (Element) xDocument.clone();
747 final Element navitree = ((Element) xDoc.getChild("navigationtree"));
748 // separate
749 ArrayList<String> itemname = new ArrayList<String>();
750 ArrayList<Integer> itemlevel = new ArrayList<Integer>();
751 ArrayList<Element> itemelm = new ArrayList<Element>();
752 @SuppressWarnings("unchecked")
753 List<Element> navitreelist = navitree.getChildren();
754 for (int i = 0; i < navitreelist.size(); i++) {
755 final Element child = navitreelist.get(i);
756 final Element col1 = (Element) (child.getChildren().get(0));
757 final Element col2 = (Element) (child.getChildren().get(1));
758 final String sText = col2.getText();
759 int level = 0;
760 try {
761 level = col1.getAttribute("lineLevel").getIntValue();
762 } catch (final Exception ignored) {
763 }
764 itemname.add(sText);
765 itemlevel.add(new Integer(level));
766 itemelm.add((Element) child.clone());
767 navitree.removeContent(child);
768 i--;
769 }
770 int[] itemnum = new int[itemname.size()];
771 for (int i = 0; i < itemname.size(); i++) {
772 itemnum[i] = i;
773 }
774 // sort
775 sortMyTreePerLevel(0, itemname.size(), 1, itemname, itemlevel, itemnum);
776 // write back
777 for (int i = 0; i < itemnum.length; i++) {
778 navitree.addContent(itemelm.get(itemnum[i]));
779 }
780 return xDoc;
781 }
782
783 private final void sortMyTreePerLevel(int von, int bis, int level, ArrayList<String> itemname, ArrayList<Integer> itemlevel,
784 int[] itemnum) {
785 if (von == bis)
786 return;
787 // System.out.println("$$$>" + von + " " + bis);
788 for (int i = von; i < bis - 1; i++) {
789 // System.out.println("III>" + i + " " + itemname.get(itemnum[i]));
790 if (itemlevel.get(itemnum[i]) != level) {
791 // System.out.println("%%%> inner sort");
792 int start = i;
793 int stop = start;
794 while (stop + 1 < bis && itemlevel.get(itemnum[stop + 1]).intValue() > level) {
795 stop++;
796 }
797 // System.out.println("--------------------");
798 sortMyTreePerLevel(start, stop + 1, level + 2, itemname, itemlevel, itemnum);
799 // System.out.println("--------------------");
800 i = stop + 1;
801 if (i >= bis)
802 continue;
803 }
804 String aktitem = itemname.get(itemnum[i]);
805 for (int j = i + 1; j < bis; j++) {
806 if (level != itemlevel.get(itemnum[j]).intValue())
807 continue;
808 // System.out.println("%%%>" + i + " " + aktitem + " " + j + " "
809 // + itemname.get(itemnum[j]) + " " + level + " " +
810 // itemlevel.get(itemnum[j]).intValue());
811 if (aktitem.compareTo(itemname.get(itemnum[j])) > 0) {
812 // must switch
813 // System.out.println("%%%> swap " + i + " with " + j);
814 int[] swap = itemnum.clone();
815 itemnum[i] = itemnum[j];
816 int ii = i;
817 for (int jj = j; jj < bis; jj++) {
818 // System.out.println("* " + ii + " " + jj);
819 itemnum[ii] = swap[jj];
820 ii++;
821 }
822 for (int jj = i; jj < j; jj++) {
823 // System.out.println("# " + ii + " " + jj);
824 itemnum[ii] = swap[jj];
825 ii++;
826 }
827 j = i;
828 aktitem = itemname.get(itemnum[i]);
829 }
830 }
831 }
832 }
833
834 /**
835 * @return Returns the pool.
836 */
837 public static MCRClassificationPool getClassificationPool() {
838 MCRSession session = MCRSessionMgr.getCurrentSession();
839 Object cp = session.get("MCRClassificationPool.instance");
840 if (cp != null && cp instanceof MCRClassificationPool) {
841 return (MCRClassificationPool) cp;
842 }
843 MCRClassificationPool classPool = new MCRClassificationPool();
844 session.put("MCRClassificationPool.instance", classPool);
845 return classPool;
846 }
847
848 private static MCRLabel getLabel(MCRCategory co, String lang) {
849 for (MCRLabel label : co.getLabels()) {
850 if (label.getLang().equals(lang)) {
851 return label;
852 }
853 }
854 return new MCRLabel();
855 }
856
857 public static void clearUserClassTable(MCRSession session) {
858 final String curSessionID = session.getID();
859 final Iterator<Map.Entry<String, String>> it = ClassUserTable.entrySet().iterator();
860 while (it.hasNext()) {
861 Map.Entry<String, String> entry = it.next();
862 if (entry.getValue().equals(curSessionID)) {
863 LOGGER.info("Release classification " + entry.getKey() + " lock.");
864 it.remove();
865 }
866 }
867 }
868
869 private MCRCategory findCategory(MCRCategory parent, String id) {
870 MCRCategory found = null;
871 for (MCRCategory cat : parent.getChildren()) {
872 if (cat.getId().getID().equals(id)) {
873 found = cat;
874 LOGGER.debug("Found Category: " + found.getId().getID());
875 break;
876 }
877 MCRCategory rFound = findCategory(cat, id);
878 if (rFound != null) {
879 found = rFound;
880 break;
881 }
882 }
883
884 return found;
885 }
886
887 private static class MCRCategoryElementFactory {
888 static Element getCategoryElement(MCRCategory category, boolean withCounter, int numberObjects) {
889 Element ce = new Element("category");
890 Collection<MCRLabel> labels = category.getLabels();
891 ce.setAttribute("ID", category.getId().getID());
892 if (withCounter) {
893 ce.setAttribute("counter", Integer.toString(numberObjects));
894 }
895
896 for (MCRLabel label : labels) {
897 ce.addContent(getElement(label));
898 }
899 for (MCRCategory child : category.getChildren()) {
900 ce.addContent(getCategoryElement(child, withCounter, numberObjects));
901 }
902 return ce;
903 }
904
905 private static Element getElement(MCRLabel label) {
906 Element le = new Element("label");
907 if (stringNotEmpty(label.getLang())) {
908 le.setAttribute("lang", label.getLang(), Namespace.XML_NAMESPACE);
909 }
910 if (stringNotEmpty(label.getText())) {
911 le.setAttribute("text", label.getText());
912 }
913 if (stringNotEmpty(label.getDescription())) {
914 le.setAttribute("description", label.getDescription());
915 }
916 return le;
917 }
918
919 private static boolean stringNotEmpty(String test) {
920 if (test != null && test.length() > 0) {
921 return true;
922 }
923 return false;
924 }
925 }
926
927 }