1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cms.gui.control;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.HierarchyManager;
38 import info.magnolia.cms.core.ItemType;
39 import info.magnolia.cms.core.NodeData;
40 import info.magnolia.cms.core.Path;
41 import info.magnolia.cms.util.MetaDataUtil;
42 import info.magnolia.cms.util.NodeDataUtil;
43 import info.magnolia.context.MgnlContext;
44 import info.magnolia.freemarker.FreemarkerUtil;
45
46 import java.util.ArrayList;
47 import java.util.Collection;
48 import java.util.Collections;
49 import java.util.Comparator;
50 import java.util.HashMap;
51 import java.util.HashSet;
52 import java.util.Iterator;
53 import java.util.List;
54 import java.util.Map;
55 import java.util.Set;
56 import java.util.TreeSet;
57
58 import javax.jcr.PropertyType;
59 import javax.jcr.RepositoryException;
60 import javax.jcr.Value;
61 import javax.servlet.http.HttpServletRequest;
62
63 import org.apache.commons.lang.StringEscapeUtils;
64 import org.apache.commons.lang.StringUtils;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67
68
69
70
71
72
73 public class Tree extends ControlImpl {
74
75 public static final String DOCROOT = "/.resources/controls/tree/";
76
77 public static final String ICONDOCROOT = "/.resources/icons/16/";
78
79 public static final String DEFAULT_ICON = ICONDOCROOT + "cubes.gif";
80
81 public static final String DEFAULT_ICON_CONTENT = ICONDOCROOT + "document_plain_earth.gif";
82
83 public static final String DEFAULT_ICON_CONTENTNODE = DEFAULT_ICON;
84
85 public static final String DEFAULT_ICON_NODEDATA = ICONDOCROOT + "cube_green.gif";
86
87
88
89
90 @Deprecated
91 public static final String ITEM_TYPE_NODEDATA = "mgnl:nodeData";
92
93 public static final int ACTION_MOVE = 0;
94
95 public static final int ACTION_COPY = 1;
96
97 public static final int ACTION_ACTIVATE = 2;
98
99 public static final int ACTION_DEACTIVATE = 3;
100
101 public static final int PASTETYPE_ABOVE = 0;
102
103 public static final int PASTETYPE_BELOW = 1;
104
105 public static final int PASTETYPE_SUB = 2;
106
107 public static final int PASTETYPE_LAST = 3;
108
109
110
111
112 private static Logger log = LoggerFactory.getLogger(Tree.class);
113
114 private String repository;
115
116 private String pathOpen;
117
118 private String pathCurrent;
119
120 private String pathSelected;
121
122 private String rootPath;
123
124 private int indentionWidth = 15;
125
126 private final List<String> itemTypes = new ArrayList<String>();
127
128 private final Set<String> strictTypes = new HashSet<String>();
129
130 private int height = 400;
131
132 private final Map<String, String> icons = new HashMap<String, String>();
133
134 private String iconOndblclick;
135
136 private String shifterExpand = DOCROOT + "shifter_EXPAND.gif";
137
138 private String shifterCollaspe = DOCROOT + "shifter_COLLAPSE.gif";
139
140 private String shifterEmpty = DOCROOT + "shifter_EMPTY.gif";
141
142 private boolean drawShifter = true;
143
144 private String javascriptTree = "mgnlTreeControl";
145
146 private List columns = new ArrayList();
147
148 private ContextMenu menu;
149
150 private Comparator sortComparator;
151
152
153
154
155 private FunctionBar functionBar;
156
157 private boolean snippetMode = true;
158
159 private String columnResizer = DOCROOT + "columnResizer.gif";
160
161 private boolean browseMode;
162
163
164
165
166 private HierarchyManager hm;
167
168
169
170
171 @Deprecated
172 public Tree(String name, String repository, HttpServletRequest request) {
173 this(name, repository);
174 }
175
176
177
178
179
180
181 public Tree(String name, String repository) {
182 this.setName(name);
183 this.setRepository(repository);
184 this.setMenu(new ContextMenu(this.getJavascriptTree()));
185 this.setFunctionBar(new FunctionBar(this.getJavascriptTree()));
186
187 this.setHierarchyManager(MgnlContext.getHierarchyManager(this.getRepository()));
188
189
190 this.setIcon(ItemType.CONTENT.getSystemName(), DEFAULT_ICON_CONTENT);
191 this.setIcon(ItemType.CONTENTNODE.getSystemName(), DEFAULT_ICON_CONTENTNODE);
192 this.setIcon(ITEM_TYPE_NODEDATA, DEFAULT_ICON_NODEDATA);
193 }
194
195
196
197
198
199
200
201 @Deprecated
202 public Tree(String repository, HttpServletRequest request) {
203 this(repository, repository, request);
204 }
205
206 public void setRepository(String s) {
207 this.repository = s;
208 }
209
210 public String getRepository() {
211 return this.repository;
212 }
213
214 public void setPathOpen(String s) {
215 this.pathOpen = s;
216 }
217
218 public String getPathOpen() {
219 return this.pathOpen;
220 }
221
222
223
224
225
226 public void setPathSelected(String s) {
227 if (StringUtils.isNotEmpty(s)) {
228 if (StringUtils.isEmpty(this.getPathOpen())) {
229 this.setPathOpen(StringUtils.substringBeforeLast(s, "/"));
230 }
231 }
232 this.pathSelected = s;
233 }
234
235 public String getPathSelected() {
236 return this.pathSelected;
237 }
238
239 @Override
240 public String getPath() {
241 if (super.getPath() != null) {
242 return super.getPath();
243 }
244
245 return ("/");
246 }
247
248 protected void setPathCurrent(String s) {
249 this.pathCurrent = s;
250 }
251
252 protected String getPathCurrent() {
253 return this.pathCurrent;
254 }
255
256 public void setIndentionWidth(int i) {
257 this.indentionWidth = i;
258 }
259
260 public int getIndentionWidth() {
261 return this.indentionWidth;
262 }
263
264 public List getItemTypes() {
265 return this.itemTypes;
266 }
267
268
269
270
271
272 @Deprecated
273 public void addItemType(String s) {
274 addItemType(s, null);
275 }
276
277
278
279
280
281
282
283
284
285
286 public void addItemType(String type, String icon) {
287 addItemType(type, icon, true);
288 }
289
290 public void addItemType(String type, boolean strict) {
291 addItemType(type, null, strict);
292 }
293
294
295
296
297
298
299
300
301
302 public void addItemType(String type, String icon, boolean strict) {
303 this.itemTypes.add(type);
304 if (icon != null) {
305 setIcon(type, icon);
306 }
307 if (strict) {
308 strictTypes.add(type);
309 } else {
310 strictTypes.remove(type);
311 }
312 }
313
314
315
316
317
318 public void addItemType(ItemType s) {
319 addItemType(s.getSystemName(), null);
320 }
321
322
323
324
325
326
327 @Deprecated
328 public void setIconPage(String src) {
329 this.setIcon(ItemType.CONTENT.getSystemName(), src);
330 }
331
332 public String getIconPage() {
333 return this.getIcon(ItemType.CONTENT.getSystemName());
334 }
335
336
337
338
339
340
341 @Deprecated
342 public void setIconContentNode(String src) {
343 this.setIcon(ItemType.CONTENTNODE.getSystemName(), src);
344 }
345
346 public String getIconContentNode() {
347 return this.getIcon(ItemType.CONTENTNODE.getSystemName());
348 }
349
350
351
352
353
354
355 @Deprecated
356 public void setIconNodeData(String src) {
357 this.setIcon(ITEM_TYPE_NODEDATA, src);
358 }
359
360 public String getIconNodeData() {
361 return this.getIcon(ITEM_TYPE_NODEDATA);
362 }
363
364 protected String getIcon(String itemType) {
365 return icons.get(itemType);
366 }
367
368 protected String getIcon(Content node, NodeData nodedata, String itemType) {
369
370 try {
371 if (node != null && node.hasMixin(ItemType.DELETED_NODE_MIXIN)) {
372 return icons.get(ItemType.DELETED_NODE_MIXIN);
373 }
374 } catch (RepositoryException e) {
375 log.error("Failed to read content of " + node.getHandle());
376 }
377 if(icons.containsKey(itemType)){
378 return icons.get(itemType);
379 }
380 return DEFAULT_ICON;
381 }
382
383
384
385
386 @Deprecated
387 public void setIcon(String typeName, String icon) {
388 addIcon(typeName, icon);
389 }
390
391 public void addIcon(String typeName, String icon) {
392 icons.put(typeName, icon);
393 }
394
395
396
397
398 public void setIconOndblclick(String s) {
399 this.iconOndblclick = s;
400 }
401
402 public String getIconOndblclick() {
403 return this.iconOndblclick;
404 }
405
406
407
408
409
410
411 public void setShifterExpand(String src) {
412 this.shifterExpand = src;
413 }
414
415 public String getShifterExpand() {
416 return this.shifterExpand;
417 }
418
419
420
421
422
423
424 public void setShifterCollapse(String src) {
425 this.shifterCollaspe = src;
426 }
427
428 public String getShifterCollapse() {
429 return this.shifterCollaspe;
430 }
431
432
433
434
435
436
437 public void setShifterEmpty(String src) {
438 this.shifterEmpty = src;
439 }
440
441 public String getShifterEmpty() {
442 return this.shifterEmpty;
443 }
444
445 public void setDrawShifter(boolean b) {
446 this.drawShifter = b;
447 }
448
449 public boolean getDrawShifter() {
450 return this.drawShifter;
451 }
452
453 public void setHeight(int i) {
454 this.height = i;
455 }
456
457 public int getHeight() {
458 return this.height;
459 }
460
461
462
463
464
465 public void setColums(List al) {
466 this.columns = al;
467 }
468
469 public List getColumns() {
470 return this.columns;
471 }
472
473 public TreeColumn getColumns(int col) {
474 return (TreeColumn) this.getColumns().get(col);
475 }
476
477 public void addColumn(TreeColumn tc) {
478 tc.setJavascriptTree(this.getJavascriptTree());
479 this.getColumns().add(tc);
480 }
481
482
483
484
485
486 public void setJavascriptTree(String variableName) {
487 this.javascriptTree = variableName;
488 this.menu.setName(variableName + "Menu");
489 }
490
491 public String getJavascriptTree() {
492 return this.javascriptTree;
493 }
494
495
496
497
498
499
500 public void setSnippetMode(boolean b) {
501 this.snippetMode = b;
502 }
503
504 public boolean getSnippetMode() {
505 return this.snippetMode;
506 }
507
508
509 public void setColumnResizer(String src) {
510 this.columnResizer = src;
511 }
512
513 public String getColumnResizer() {
514 return this.columnResizer;
515 }
516
517 public String createNode(String itemType) {
518 return this.createNode("untitled", itemType);
519 }
520
521
522
523
524
525
526
527 public String createNode(String label, String itemType) {
528 try {
529 Content parentNode = getHierarchyManager().getContent(this.getPath());
530 String name = getUniqueLabel(label);
531 if (itemType.equals(ITEM_TYPE_NODEDATA)) {
532 parentNode.createNodeData(name);
533 } else {
534 Content newNode;
535 newNode = parentNode.createContent(name, itemType);
536 newNode.getMetaData().setAuthorId(MgnlContext.getUser().getName());
537 newNode.getMetaData().setCreationDate();
538 newNode.getMetaData().setModificationDate();
539 }
540 parentNode.save();
541 return name;
542 } catch (Exception e) {
543 log.error(e.getMessage(), e);
544 return StringUtils.EMPTY;
545 }
546
547 }
548
549 public String saveNodeData(String nodeDataName, String value, boolean isMeta) {
550 String returnValue = StringUtils.EMPTY;
551 try {
552 Content content = getHierarchyManager().getContent(this.getPath());
553 if (!isMeta) {
554 NodeData node;
555 int type = PropertyType.STRING;
556 if (!content.getNodeData(nodeDataName).isExist()) {
557 node = content.createNodeData(nodeDataName);
558 }
559 else {
560 node = content.getNodeData(nodeDataName);
561 type = node.getType();
562 }
563
564 if (node.isMultiValue() != NodeData.MULTIVALUE_TRUE) {
565 switch (type) {
566 case PropertyType.STRING:
567 node.setValue(value);
568 break;
569 case PropertyType.BOOLEAN:
570 if (value.equals("true")) {
571 node.setValue(true);
572 }
573 else {
574 node.setValue(false);
575 }
576 break;
577 case PropertyType.DOUBLE:
578 try {
579 node.setValue(Double.valueOf(value).doubleValue());
580 }
581 catch (Exception e) {
582 node.setValue(0);
583 }
584 break;
585 case PropertyType.LONG:
586 try {
587 node.setValue(Long.valueOf(value).longValue());
588 }
589 catch (Exception e) {
590 node.setValue(0);
591 }
592 break;
593 case PropertyType.DATE:
594
595 break;
596 }
597 }
598 content.updateMetaData();
599 content.save();
600 returnValue = NodeDataUtil.getValueString(node);
601 }
602 else {
603 content.getMetaData().setProperty(nodeDataName, value);
604 content.updateMetaData();
605 content.save();
606 returnValue = MetaDataUtil.getPropertyValueString(content, nodeDataName);
607 }
608 }
609 catch (Exception e) {
610 if (log.isDebugEnabled()) {
611 log.debug("Exception caught: " + e.getMessage(), e);
612 }
613 }
614 return returnValue;
615 }
616
617 public String saveNodeDataType(String nodeDataName, int type) {
618 try {
619 Content content = getHierarchyManager().getContent(this.getPath());
620 Value value = null;
621 if (content.getNodeData(nodeDataName).isExist()) {
622 value = content.getNodeData(nodeDataName).getValue();
623 content.deleteNodeData(nodeDataName);
624 }
625 NodeData node = content.createNodeData(nodeDataName);
626 if (value != null && node.isMultiValue() != NodeData.MULTIVALUE_TRUE) {
627 switch (type) {
628 case PropertyType.STRING:
629 node.setValue(value.getString());
630 break;
631 case PropertyType.BOOLEAN:
632 if (value != null && value.getBoolean()) {
633 node.setValue(true);
634 }
635 else {
636 node.setValue(false);
637 }
638 break;
639 case PropertyType.DOUBLE:
640 try {
641 node.setValue(value.getDouble());
642 }
643 catch (Exception e) {
644 node.setValue(0);
645 }
646 break;
647 case PropertyType.LONG:
648 try {
649 node.setValue(value.getLong());
650 }
651 catch (Exception e) {
652 node.setValue(0);
653 }
654 break;
655 case PropertyType.DATE:
656
657 break;
658 }
659 }
660 content.updateMetaData();
661 content.save();
662 return PropertyType.nameFromValue(content.getNodeData(nodeDataName).getType());
663
664 }
665 catch (Exception e) {
666 if (log.isDebugEnabled()) {
667 log.debug("Exception caught: " + e.getMessage(), e);
668 }
669 }
670 return StringUtils.EMPTY;
671 }
672
673
674
675
676
677
678 protected String getUniqueLabel(String label) {
679 String slash = "/";
680 boolean isRoot = false;
681 if ("/".equals(getPath())) {
682 isRoot = true;
683 slash = StringUtils.EMPTY;
684 }
685 if (getHierarchyManager().isExist(this.getPath() + slash + label)) {
686
687 if (isRoot) {
688 label = Path.getUniqueLabel(getHierarchyManager(), StringUtils.EMPTY, label);
689 } else {
690 label = Path.getUniqueLabel(getHierarchyManager(), this.getPath(), label);
691 }
692 }
693 return label;
694 }
695
696 @Override
697 public String getHtml() {
698 StringBuffer html = new StringBuffer();
699 html.append(this.getHtmlPre());
700
701 if (!this.getSnippetMode()) {
702 html.append(this.getHtmlHeader());
703 }
704 this.setPathCurrent(this.getPath());
705 html.append(this.getHtmlChildren());
706 if (!this.getSnippetMode()) {
707 html.append(this.getHtmlFooter());
708 }
709 html.append(this.getHtmlPost());
710 return html.toString();
711 }
712
713 public String getHtmlHeader() {
714
715 StringBuffer str = new StringBuffer();
716 try {
717 Map params = populateTemplateParameters();
718 str.append(FreemarkerUtil.process("info/magnolia/cms/gui/control/TreeHeader.ftl", params));
719 }
720 catch (Exception e) {
721 log.error("can't render tree header", e);
722 }
723 return str.toString();
724 }
725
726 public String getHtmlFooter() {
727 StringBuffer html = new StringBuffer();
728 html.append("</div>");
729
730 Map params = populateTemplateParameters();
731
732
733 html.append(FreemarkerUtil.process("info/magnolia/cms/gui/control/TreeFooter.ftl", params));
734
735 return html.toString();
736 }
737
738 protected Map populateTemplateParameters() {
739 boolean permissionWrite = true;
740 try {
741 Content root = getHierarchyManager().getContent(this.getPath());
742 permissionWrite = root.isGranted(info.magnolia.cms.security.Permission.WRITE);
743 }
744 catch (RepositoryException e) {
745 if (log.isDebugEnabled()) {
746 log.debug("Exception caught: " + e.getMessage(), e);
747 }
748 }
749
750
751
752 String lineId = this.getJavascriptTree() + "_" + this.getPath() + "_LineInter";
753
754
755 Map<String, Object> params = new HashMap<String, Object>();
756 params.put("tree", this);
757 params.put("PASTETYPE_SUB", new Integer(Tree.PASTETYPE_SUB));
758 params.put("DOCROOT", Tree.DOCROOT);
759 params.put("lineId", lineId);
760 params.put("permissionWrite", Boolean.valueOf(permissionWrite));
761 params.put("columns", this.getColumns());
762 params.put("menu", this.getMenu());
763 params.put("treeCssClass", "mgnlTreeDiv");
764 if (this.isBrowseMode()) {
765 params.put("treeCssClass", "mgnlTreeBrowseModeDiv mgnlTreeDiv");
766 }
767 return params;
768 }
769
770 public String getHtmlBranch() {
771 return StringUtils.EMPTY;
772 }
773
774 public String getHtmlChildren() {
775 StringBuffer html = new StringBuffer();
776 Content parentNode;
777 try {
778 parentNode = getHierarchyManager().getContent(this.getPathCurrent());
779
780 for (int i = 0; i < this.getItemTypes().size(); i++) {
781 String type = (String) this.getItemTypes().get(i);
782 if (hasSub(parentNode, type)) {
783 html.append(this.getHtmlChildrenOfOneType(parentNode, type));
784 }
785 }
786 }
787 catch (RepositoryException e) {
788 if (log.isDebugEnabled()) {
789 log.debug("Exception caught: " + e.getMessage(), e);
790 }
791 }
792 return html.toString();
793 }
794
795 public String getHtmlChildrenOfOneType(Content parentNode, String itemType) {
796 StringBuffer html = new StringBuffer();
797 try {
798 Iterator it = collectRenderedItems(parentNode, itemType);
799 while (it.hasNext()) {
800 Object maybeContent = it.next();
801 if (maybeContent instanceof Content) {
802 Content c = (Content) maybeContent;
803
804 if (strictTypes.contains(itemType) && !c.getItemType().getSystemName().equals(itemType)) {
805 continue;
806 }
807 }
808 getHtmlOfSingleItem(html, parentNode, itemType, maybeContent);
809 }
810 }
811 catch (RepositoryException e) {
812 if (log.isDebugEnabled()) {
813 log.debug("Exception caught: " + e.getMessage(), e);
814 }
815 }
816 return html.toString();
817 }
818
819 protected void getHtmlOfSingleItem(StringBuffer html, Content parentNode, String itemType, Object item) throws RepositoryException {
820 Content c = null;
821 NodeData d = null;
822 String handle;
823 String name;
824 boolean hasSub = false;
825 boolean showSub = false;
826 boolean isActivated = false;
827 boolean isDeleted = false;
828 boolean permissionWrite = false;
829 boolean permissionWriteParent = false;
830 if (itemType.equals(ITEM_TYPE_NODEDATA)) {
831 d = (NodeData) item;
832 handle = d.getHandle();
833 name = d.getName();
834
835 if (d.isGranted(info.magnolia.cms.security.Permission.WRITE) && d.isMultiValue() != NodeData.MULTIVALUE_TRUE) {
836 permissionWrite = true;
837 }
838 }
839 else {
840 c = (Content) item;
841
842 handle = c.getHandle();
843 if (this.getColumns().size() == 0) {
844 name = c.getName();
845 }
846 else {
847 this.getColumns(0).setWebsiteNode(c);
848 name = this.getColumns(0).getHtml();
849 }
850 if (c.isGranted(info.magnolia.cms.security.Permission.WRITE)) {
851 permissionWrite = true;
852 }
853 if (c.hasMixin(ItemType.DELETED_NODE_MIXIN)) {
854 isDeleted = true;
855 }
856 if (c.getAncestor(c.getLevel() - 1).isGranted(info.magnolia.cms.security.Permission.WRITE)) {
857 permissionWriteParent = true;
858 }
859 isActivated = c.getMetaData().getIsActivated();
860 for (int i = 0; i < this.getItemTypes().size(); i++) {
861 String type = (String) this.getItemTypes().get(i);
862
863 hasSub = hasSub(c, type);
864
865 if (hasSub) {
866 if (this.getPathOpen() != null
867 && (this.getPathOpen().indexOf(handle + "/") == 0 || this.getPathOpen().equals(handle))) {
868 showSub = true;
869 }
870 break;
871 }
872 }
873 }
874
875
876 if (!showNode(c, d, itemType)) {
877 return;
878 }
879
880 String icon = getIcon(c, d, itemType);
881
882 String idPre = this.javascriptTree + "_" + handle;
883 String jsHighlightNode = this.javascriptTree + ".nodeHighlight(this,'"
884 + handle
885 + "',"
886 + Boolean.toString(permissionWrite)
887 + ");";
888 String jsResetNode = this.javascriptTree + ".nodeReset(this,'" + handle + "');";
889 String jsSelectNode = this.javascriptTree + ".selectNode('"
890 + handle
891 + "',"
892 + Boolean.toString(permissionWrite)
893 + ",'"
894 + itemType
895 + "');";
896 String jsExpandNode;
897 if (this.getDrawShifter()) {
898 jsExpandNode = this.javascriptTree + ".expandNode('" + handle + "');";
899 }
900 else {
901 jsExpandNode = jsSelectNode;
902 }
903 String jsHighlightLine = this.javascriptTree + ".moveNodeHighlightLine('" + idPre + "_LineInter');";
904 String jsResetLine = this.javascriptTree + ".moveNodeResetLine('" + idPre + "_LineInter');";
905
906
907
908 if (permissionWriteParent) {
909 html.append("<div id=\"");
910 html.append(idPre);
911 html.append("_LineInter\" class=\"mgnlTreeLineInter mgnlLineEnabled\" onmouseover=\"");
912 html.append(jsHighlightLine);
913 html.append("\" onmouseout=\"");
914 html.append(jsResetLine);
915 html.append("\" onmousedown=\"");
916 html.append(this.javascriptTree);
917 html.append(".pasteNode('");
918 html.append(handle);
919 html.append("'," + Tree.PASTETYPE_ABOVE + ",true);\" ></div>");
920 }
921 else {
922 html.append("<div id=\"");
923 html.append(idPre);
924 html.append("_LineInter\" class=\"mgnlTreeLineInter mgnlLineDisabled\"></div>");
925 }
926
927 html.append("<div id=\"");
928 html.append(idPre);
929 html.append("_DivMain\" style=\"position:relative;top:0;left:0;width:100%;height:18px;\">");
930 html.append(" ");
931
932 html.append("<span id=\"");
933 html.append(idPre);
934 html.append("_Column0Outer\" class=\"mgnlTreeColumn ");
935 html.append(this.javascriptTree);
936 html.append("CssClassColumn0\" style=\"padding-left:");
937
938 html.append(getPaddingLeft(parentNode));
939 html.append("px;\">");
940 if (this.getDrawShifter()) {
941 String shifter = StringUtils.EMPTY;
942 if (hasSub) {
943 if (showSub) {
944 if (this.getShifterCollapse() != null) {
945 shifter = this.getShifterCollapse();
946 }
947 }
948 else {
949 if (this.getShifterExpand() != null) {
950 shifter = this.getShifterExpand();
951 }
952 }
953 }
954 else {
955 if (this.getShifterEmpty() != null) {
956 shifter = this.getShifterEmpty();
957 }
958 }
959 if (StringUtils.isNotEmpty(shifter)) {
960 html.append("<img id=\"");
961 html.append(idPre);
962 html.append("_Shifter\" onmousedown=\"");
963 html.append(this.javascriptTree);
964 html.append(".shifterDown('");
965 html.append(handle);
966 html.append("');\" onmouseout=\"");
967 html.append(this.javascriptTree);
968 html.append(".shifterOut();\" class=\"mgnlTreeShifter\" src=\"");
969 html.append(this.getRequest().getContextPath());
970 html.append(shifter);
971 html.append("\" />");
972 }
973 }
974 html.append("<span id=\"");
975 html.append(idPre);
976 html.append("_Name\" onmouseover=\"");
977 html.append(jsHighlightNode);
978 html.append("\" onmouseout=\"");
979 html.append(jsResetNode);
980 html.append("\" onmousedown=\"");
981 html.append(jsSelectNode);
982 html.append(this.javascriptTree);
983 html.append(".pasteNode('");
984 html.append(handle);
985 html.append("'," + Tree.PASTETYPE_SUB + ",");
986 html.append(permissionWrite);
987 html.append(");\">");
988 if (StringUtils.isNotEmpty(icon)) {
989 html.append("<img id=\"");
990 html.append(idPre);
991 html.append("_Icon\" class=\"mgnlTreeIcon\" src=\"");
992 html.append(this.getRequest().getContextPath());
993 html.append(icon);
994 html.append("\" onmousedown=\"");
995 html.append(jsExpandNode);
996 html.append("\"");
997 if (this.getIconOndblclick() != null) {
998 html.append(" ondblclick=\"");
999 html.append(this.getIconOndblclick());
1000 html.append("\"");
1001 }
1002 html.append(" />");
1003 }
1004 String dblclick = StringUtils.EMPTY;
1005 String htmlEdit = this.getColumns(0).getHtmlEdit();
1006 if (permissionWrite && StringUtils.isNotEmpty(htmlEdit)) {
1007 dblclick = " ondblclick=\"" + this.javascriptTree + ".editNodeData(this,'" + handle + "',0,'"+ StringUtils.replace(htmlEdit, "\"", """) + "');\"";
1008 }
1009 html.append("<span class=\"mgnlTreeText\" id=\"");
1010 html.append(idPre);
1011 html.append("_Column0Main\"");
1012 html.append(dblclick);
1013 html.append(">");
1014 html.append(name);
1015 html.append("</span></span></span>");
1016
1017
1018 html.append(new Hidden(idPre + "_PermissionWrite", Boolean.toString(permissionWrite), false).getHtml());
1019 html.append(new Hidden(idPre + "_IsDeleted", Boolean.toString(isDeleted), false).getHtml());
1020 html.append(new Hidden(idPre + "_ItemType", itemType, false).getHtml());
1021 html.append(new Hidden(idPre + "_IsActivated", Boolean.toString(isActivated), false).getHtml());
1022
1023
1024 onGetHtmlOfSingleItem(html, parentNode, itemType, item , idPre);
1025
1026 for (int i = 1; i < this.getColumns().size(); i++) {
1027 String str = StringUtils.EMPTY;
1028 TreeColumn tc = this.getColumns(i);
1029 if (!itemType.equals(ITEM_TYPE_NODEDATA)) {
1030
1031 if (!tc.getIsNodeDataType() && !tc.getIsNodeDataValue()) {
1032 tc.setWebsiteNode(c);
1033 tc.setId(handle);
1034 str = tc.getHtml();
1035 }
1036 }
1037 else {
1038 if (tc.getIsNodeDataType()) {
1039 str = NodeDataUtil.getTypeName(d);
1040 }
1041 else if (tc.getIsNodeDataValue()) {
1042 final String stringValue = NodeDataUtil.getValueString(d);
1043 str = StringEscapeUtils.escapeXml(stringValue);
1044 }
1045 if (StringUtils.isEmpty(str)) {
1046 str = TreeColumn.EMPTY;
1047 }
1048 tc.setName(name);
1049 }
1050 tc.setEvent("onmouseover", jsHighlightNode, true);
1051 tc.setEvent("onmouseout", jsResetNode, true);
1052 tc.setEvent("onmousedown", jsSelectNode, true);
1053 html.append("<span class=\"mgnlTreeColumn ");
1054 html.append(this.javascriptTree);
1055 html.append("CssClassColumn");
1056 html.append(i);
1057 html.append("\"><span id=\"");
1058 html.append(idPre);
1059 html.append("_Column");
1060 html.append(i);
1061 html.append("Main\"");
1062 html.append(tc.getHtmlCssClass());
1063 html.append(tc.getHtmlEvents());
1064 htmlEdit = tc.getHtmlEdit();
1065 if (permissionWrite && StringUtils.isNotEmpty(htmlEdit)) {
1066 html.append(" ondblclick=\"");
1067 html.append(this.javascriptTree);
1068 html.append(".editNodeData(this,'");
1069 html.append(handle);
1070 html.append("',");
1071 html.append(i);
1072 html.append(",'");
1073 html.append(StringUtils.replace(htmlEdit, "\"", """));
1074 html.append("');\"");
1075 html.append(",'");
1076
1077 }
1078 html.append(">");
1079 html.append(str);
1080 html.append("</span></span>");
1081 }
1082 html.append("</div>");
1083 String display = "none";
1084 if (showSub) {
1085 display = "block";
1086 }
1087 html.append("<div id=\"");
1088 html.append(idPre);
1089 html.append("_DivSub\" style=\"display:");
1090 html.append(display);
1091 html.append(";\">");
1092 if (hasSub) {
1093 if (showSub) {
1094 String pathRemaining = this.getPathOpen().substring(this.getPathCurrent().length());
1095 if (pathRemaining.length() > 0) {
1096
1097 String slash = "/";
1098 if (this.getPathCurrent().equals("/")) {
1099
1100 slash = StringUtils.EMPTY;
1101 }
1102 else {
1103 pathRemaining = pathRemaining.substring(1);
1104 }
1105 String nextChunk = StringUtils.substringBefore(pathRemaining, "/");
1106
1107 String pathNext = this.getPathCurrent() + slash + nextChunk;
1108 this.setPathCurrent(pathNext);
1109 html.append(this.getHtmlChildren());
1110 }
1111 }
1112 }
1113 html.append("</div>\n");
1114
1115 }
1116
1117 protected void onGetHtmlOfSingleItem(StringBuffer html, Content parentNode, String itemType, Object item, String idPre) {
1118 }
1119
1120 protected Iterator collectRenderedItems(Content parentNode, String itemType) {
1121 Iterator it;
1122 if (itemType.equalsIgnoreCase(ITEM_TYPE_NODEDATA)) {
1123 List nodeDatas = new ArrayList(parentNode.getNodeDataCollection());
1124
1125 Collections.sort(nodeDatas, new Comparator() {
1126
1127 @Override
1128 public int compare(Object arg0, Object arg1) {
1129 return ((NodeData) arg0).getName().compareTo(((NodeData) arg1).getName());
1130 }
1131 });
1132 it = nodeDatas.iterator();
1133 }
1134 else {
1135 Collection nodes = parentNode.getChildren(itemType);
1136 Comparator comp = this.getSortComparator();
1137 if(comp != null){
1138 Collection sortedNodes = new TreeSet(comp);
1139 sortedNodes.addAll(nodes);
1140 nodes = sortedNodes;
1141 }
1142 it = nodes.iterator();
1143 }
1144 return it;
1145 }
1146
1147 protected int getPaddingLeft(Content parentNode) throws RepositoryException {
1148 int left = (parentNode.getLevel() - StringUtils.countMatches(getRootPath(), "/")) * this.getIndentionWidth();
1149 int paddingLeft = left + 8;
1150 if (paddingLeft < 8) {
1151 paddingLeft = 8;
1152 }
1153 return paddingLeft;
1154 }
1155
1156 protected boolean hasSub(Content c, String type) {
1157 int size;
1158 if (type.equalsIgnoreCase(ITEM_TYPE_NODEDATA)) {
1159 size = c.getNodeDataCollection().size();
1160 }
1161 else {
1162 size = c.getChildren(type).size();
1163 }
1164 return size > 0;
1165 }
1166
1167
1168
1169
1170
1171
1172
1173
1174 protected boolean showNode(Content node, NodeData nodedata, String itemType) {
1175 return true;
1176 }
1177
1178
1179
1180
1181 public void addMenuItem(ContextMenuItem item) {
1182 menu.addMenuItem(item);
1183 }
1184
1185
1186
1187
1188 public void addFunctionBarItem(FunctionBarItem item) {
1189 if (item != null) {
1190 item.setJavascriptMenuName(functionBar.getJavascriptName());
1191 }
1192 functionBar.addMenuItem(item);
1193 }
1194
1195
1196
1197
1198 public void addFunctionBarItemFromContextMenu(String itemName) {
1199 final ContextMenuItem menuItem = getMenu().getMenuItemByName(itemName);
1200 if (menuItem != null) {
1201 addFunctionBarItem(new FunctionBarItem(menuItem));
1202 }
1203 }
1204
1205
1206
1207
1208 public void addSeparator() {
1209 menu.addMenuItem(null);
1210 }
1211
1212 public ContextMenu getMenu() {
1213 return this.menu;
1214 }
1215
1216
1217
1218
1219 public FunctionBar getFunctionBar() {
1220 return this.functionBar;
1221 }
1222
1223 public void setMenu(ContextMenu menu) {
1224 this.menu = menu;
1225 }
1226
1227
1228
1229
1230 public void setFunctionBar(FunctionBar functionBar) {
1231 this.functionBar = functionBar;
1232 }
1233
1234
1235
1236
1237 public boolean isBrowseMode() {
1238 return browseMode;
1239 }
1240
1241
1242
1243
1244 public void setBrowseMode(boolean browseMode) {
1245 this.browseMode = browseMode;
1246 }
1247
1248
1249
1250
1251 public HierarchyManager getHierarchyManager() {
1252 return hm;
1253 }
1254
1255
1256
1257
1258 private void setHierarchyManager(HierarchyManager hm) {
1259 this.hm = hm;
1260 }
1261
1262
1263 public Comparator getSortComparator() {
1264 return sortComparator;
1265 }
1266
1267
1268 public void setSortComparator(Comparator sortComperator) {
1269 this.sortComparator = sortComperator;
1270 }
1271
1272 public String getRootPath() {
1273 return rootPath;
1274 }
1275
1276 public void setRootPath(String rootPath) {
1277 this.rootPath = rootPath;
1278 }
1279
1280
1281 }