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