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