001: /**
002: * $Id: TreeViewerBean.java,v 1.22 2005/11/09 23:27:45 rt94277 Exp $
003: * Copyright 2005 Sun Microsystems, Inc. All
004: * rights reserved. Use of this product is subject
005: * to license terms. Federal Acquisitions:
006: * Commercial Software -- Government Users
007: * Subject to Standard License Terms and
008: * Conditions.
009: *
010: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
011: * are trademarks or registered trademarks of Sun Microsystems,
012: * Inc. in the United States and other countries.
013: */package com.sun.portal.admin.console.desktop;
014:
015: import com.sun.portal.admin.common.DesktopConstants;
016: import com.sun.portal.admin.common.AttrOptionConstants;
017: import com.sun.portal.admin.common.util.AdminClientUtil;
018: import com.sun.portal.admin.console.common.PortalBaseBean;
019:
020: import com.sun.web.ui.model.Option;
021: import com.sun.web.ui.component.Tree;
022: import com.sun.web.ui.component.TreeNode;
023: import com.sun.web.ui.component.ImageComponent;
024: import com.sun.web.ui.component.Hyperlink;
025:
026: import java.util.Map;
027: import java.util.HashMap;
028: import java.util.HashSet;
029: import java.util.Set;
030: import java.util.Collections;
031: import java.util.ArrayList;
032: import java.util.Iterator;
033: import java.util.List;
034: import java.util.logging.Level;
035:
036: import java.net.URLEncoder;
037: import java.io.UnsupportedEncodingException;
038:
039: import javax.faces.event.ActionEvent;
040: import javax.faces.context.FacesContext;
041: import javax.faces.el.VariableResolver;
042: import javax.faces.component.UIComponent;
043: import javax.faces.component.UIViewRoot;
044: import javax.management.ObjectName;
045:
046: /**
047: * Bean that handles the Navigation frame under the Desktop Manager. This bean
048: * is responsible for handling and managing the data and events related to the
049: * tree and other objects in the navigation frame.
050: *
051: * NOTE: This Bean is using dynamic binding. The contents of the tree, TreeNode
052: * objects are created at runtime. Due to a limitation in JSF/Lockhart, for
053: * components that use dynamic binding the get and set methods are only invoked
054: * once on the component in the session. Hence the only way to get the content
055: * of the tree refreshed after initial get/set is by the method invocation of
056: * the viewChange event. For page refresh operations this is achieved by using
057: * Javascript to set values to hidden fields and submitting the form to ensure
058: * that the viewChange method is invoked on the bean.
059: */
060: public class TreeViewerBean extends PortalBaseBean implements
061: DesktopConstants {
062:
063: /**
064: * String that identifies the DOM tree of the merged DP Document
065: */
066: public static final String TYPE_PHYSICAL_TREE = "0";
067: // Tree form Ids
068: private static final String TREE_ID = "cTree";
069: private static final String TREE_FORM_ID = "TreeViewer";
070:
071: // Icon image urls
072: private static final String ROOT_CONTAINER_ICON = "/images/dtree/root_container.gif";
073: private static final String VISIBLE_CONTAINER_ICON = "/images/dtree/container.gif";
074: private static final String VISIBLE_CHANNEL_ICON = "/images/dtree/channel.gif";
075: private static final String VISIBLE_PORTLET_CHANNEL_ICON = "/images/dtree/local_portlet_channel.gif";
076: private static final String VISIBLE_REMOTE_PORTLET_CHANNEL_ICON = "/images/dtree/remote_portlet_channel.gif";
077: private static final String INVISIBLE_CONTAINER_ICON = "/images/dtree/container_notvisible.gif";
078: private static final String INVISIBLE_CHANNEL_ICON = "/images/dtree/channel_notvisible.gif";
079: private static final String INVISIBLE_PORTLET_CHANNEL_ICON = "/images/dtree/local_portlet_channel_notvisible.gif";
080: private static final String INVISIBLE_REMOTE_PORTLET_CHANNEL_ICON = "/images/dtree/remote_portlet_channel_notvisible.gif";
081:
082: private static final String INDENT = "- ";
083:
084: private Tree cTree = null;
085: private TreeNode rootTreeNode = null;
086: private TreeNode selectedNode = null;
087: private String selectedChannel = null;
088: private String currentView = null;
089: private List viewTypes = Collections.EMPTY_LIST;
090: private Set topNodes = Collections.EMPTY_SET;
091:
092: /**
093: * Constructor
094: */
095: public TreeViewerBean() {
096: log(Level.FINEST, "Tree Bean Constructor Invoked...");
097: }
098:
099: /**
100: * Fetches the contents for the View Menu
101: *
102: * @return An option array of items to be displayed in the menu
103: */
104: public List getViewTypes() {
105:
106: if (!viewTypes.isEmpty()) {
107: return viewTypes;
108: }
109:
110: String defaultChannel = "";
111:
112: try {
113:
114: Object[] params = { getCurrentDN() };
115: String[] signature = { "java.lang.String" };
116: String methodName = "getTopLevelChannels";
117:
118: // Get the Display Profile MBean Object Name
119: ObjectName objName = AdminClientUtil
120: .getDisplayProfileMBeanObjectName(
121: AdminClientUtil.DEFAULT_DOMAIN,
122: getPortalId());
123:
124: // Invoke the get method on the portal Desktop MBean to fetch the
125: // list of top level container nodes available at the current DN
126: topNodes = (Set) getMBeanServerConnection().invoke(objName,
127: methodName, params, signature);
128: // Get the Portal Object Name
129: ObjectName pObjName = AdminClientUtil
130: .getPortalMBeanObjectName(
131: AdminClientUtil.DEFAULT_DOMAIN,
132: getPortalId());
133:
134: Set attrNames = new HashSet();
135: attrNames.add("DefaultChannel"); // TODO - Pick from constants file
136: Map options = new HashMap();
137: options.put(AttrOptionConstants.OPT_COMPONENT, "desktop");
138: options.put("operation", "get");
139: options.put(AttrOptionConstants.OPT_ATTR_NAMES, attrNames);
140: if (!((String) getCurrentDN()).equals(GLOBAL_LOCATION_DN)) {
141: options.put(AttrOptionConstants.OPT_DN, getCurrentDN());
142: }
143:
144: Object[] prms = { options };
145: String[] sig = { "java.util.Map" };
146: methodName = "getAttributes";
147:
148: // Invoke the method to fetch the default channel name at the
149: // current DN for this portal
150: Map attrVals = (Map) getMBeanServerConnection().invoke(
151: pObjName, methodName, prms, sig);
152: List values = (List) attrVals.get(DEFAULT_CHANNEL);
153: if (values != null && !values.isEmpty()) {
154: String val = (String) values.get(0);
155: if (val != null) {
156: defaultChannel = val.trim();
157: }
158: }
159:
160: } catch (Exception e) {
161: log(
162: Level.SEVERE,
163: "TreeViewerBean.getViewTypes(): Error Fetching Top Level Container set",
164: e);
165: }
166:
167: log(Level.FINEST, "Top Level Container Set: " + topNodes);
168: log(Level.FINEST, "Default Channel Value: " + defaultChannel);
169:
170: String pTreeLbl = getI18NString("label.dom.tree");
171: Option pTreeOpt = new Option(TYPE_PHYSICAL_TREE, pTreeLbl);
172:
173: String line = "========";
174: StringBuffer dViewsLabel = new StringBuffer();
175: dViewsLabel.append(line).append(" ").append(
176: getI18NString("label.visual.tree")).append(" ").append(
177: line);
178: Option dViewsOpt = new Option("", dViewsLabel.toString());
179: dViewsOpt.setDisabled(true);
180:
181: // Add both views to the list of viewTypes
182: // Initialize the viewTypes
183: viewTypes = new ArrayList();
184: viewTypes.add(pTreeOpt);
185: viewTypes.add(dViewsOpt);
186: // Initialize a flag to check if default channel exists in set of
187: // top level containers
188: boolean exists = false;
189: if (defaultChannel != null) {
190: String dContainerLabel = INDENT
191: + getTruncatedString(defaultChannel) + " ["
192: + getI18NString("label.view.default") + "]";
193: Option dContainerOpt = new Option(defaultChannel,
194: dContainerLabel);
195:
196: // Check if the default channel exists in the list of top level
197: // containers.
198: exists = topNodes.contains(defaultChannel);
199: // That means the value set to the default channel service attribute
200: // is invalid and is available at the current DN. So disable this
201: // option in the viewType menu
202: dContainerOpt.setDisabled(!exists);
203:
204: // Add this Default Channel Option to the viewTypes menu items
205: viewTypes.add(dContainerOpt);
206: } else {
207: // If its null set it to empty string
208: defaultChannel = "";
209: }
210:
211: // Minimum of two options Physical and Visual tree are always displayed
212: // If the top level container list is not empty we will populate the
213: // viewOptions array with the names of the containers
214: Iterator itr = topNodes.iterator();
215: while (itr.hasNext()) {
216: String cName = (String) itr.next();
217: if (!cName.equals(defaultChannel)) {
218: String cVisibleName = INDENT
219: + getTruncatedString(cName);
220: Option containerOption = new Option(cName, cVisibleName);
221: containerOption.setTooltip(cName);
222: viewTypes.add(containerOption);
223: }
224: }
225:
226: return viewTypes;
227: }
228:
229: private String getTruncatedString(String str) {
230: String output;
231: // If the name of the container is more than 25 chars, prune it
232: if (str.length() > 25) {
233: output = str.substring(0, 25) + "...";
234: } else {
235: output = str;
236: }
237: return output;
238: }
239:
240: private void initCurrentView() {
241:
242: // Initialize currentView to physical tree
243: currentView = TYPE_PHYSICAL_TREE;
244:
245: // Get the selected container sesssion attribute to decide the value
246: // that should be set for the currentView
247: String lastView = (String) getSessionAttribute(ATTR_SELECTED_TREE_CONTAINER);
248: if (lastView == null) {
249: // Set to empty string. The first visit to the tree. So no value
250: // set into the session.
251: lastView = "";
252: }
253: log(Level.FINEST, "Last Selected View: " + lastView);
254:
255: // Iterate through all options to check if the selectedContainer is one
256: // of the top level containers.
257: Iterator itr = viewTypes.iterator();
258: while (itr.hasNext()) {
259: // Get the name of the container in this option
260: Option option = (Option) itr.next();
261: String containerName = (String) option.getValue();
262: // If current option is not disabled and containerName is same as
263: // selectedContainer value set currentView to it and end loop
264: if (!option.isDisabled() && containerName.equals(lastView)) {
265: // If equals then set it as currentView and break out of loop
266: currentView = lastView;
267: break;
268: }
269: }
270:
271: // After looping through all optios if the currentView is still set to
272: // physical tree then try to set currentView to Default Channel Value
273: // if its not disabled.
274: if (currentView.equals(TYPE_PHYSICAL_TREE)
275: && !lastView.equals(TYPE_PHYSICAL_TREE)) {
276:
277: if (viewTypes.size() > 2) {
278: Option option = (Option) viewTypes.get(2);
279: if (!option.isDisabled()) {
280: currentView = (String) option.getValue();
281: }
282: }
283: }
284: }
285:
286: /**
287: * Gets the view selected by the user
288: *
289: * @return A string representing the current view
290: */
291: public String getCurrentView() {
292: // If currentView is not initialized then maybe the getViewTypes is not
293: // already invoked. Invoke getViewTypes
294: if (viewTypes.isEmpty()) {
295: getViewTypes();
296: initCurrentView();
297: }
298:
299: return currentView;
300: }
301:
302: /**
303: * Sets the view item selected by the user
304: *
305: * @param viewType A string representing the current selected view
306: */
307: public void setCurrentView(String viewType) {
308: currentView = viewType;
309: }
310:
311: /**
312: * This method gets the value for the string that represents the top DPNode
313: * that is displayed on the tree. A null is returned if the tree cannot be
314: * displayed
315: * @return Name of the DPNode represented by the top level node in the tree
316: */
317: public String getDefaultChannel() {
318: String channel;
319: // If cTree is null invoke resetTree. That will initialize it
320: if (cTree == null) {
321: log(Level.FINEST, "Tree is Null. Invoked createTree()");
322: cTree = createTree(getCurrentView());
323: }
324:
325: if (selectedNode != null) {
326: channel = selectedNode.getText();
327: } else {
328: channel = cTree.getText();
329: }
330: String encodedName = channel;
331: if (channel != null) {
332: try {
333: encodedName = URLEncoder.encode(channel,
334: DEFAULT_CHARSET);
335: } catch (UnsupportedEncodingException uee) {
336: encodedName = channel;
337: }
338: }
339: return encodedName;
340: }
341:
342: /**
343: * This method gets the value for the string that Client HTML Id for the
344: * tree node that is currently selected or set into the session. If the
345: * node does not exist in the current tree it will return a null
346: * @return Client Id of the selected tree node as a string
347: */
348: public String getDefaultChannelNodeId() {
349: // If cTree is null invoke resetTree. That will initialize it
350: if (cTree == null) {
351: log(Level.FINEST, "Tree is Null. Invoked createTree()");
352: cTree = createTree(getCurrentView());
353: }
354:
355: FacesContext context = FacesContext.getCurrentInstance();
356: // Initialize this to a element id thats does not exist in the page
357: String nodeId = "**";
358: // If the selected node is not null get the nodes element id
359: if (selectedNode != null) {
360: nodeId = selectedNode.getClientId(context);
361: }
362:
363: return nodeId;
364: }
365:
366: /**
367: * Prepares are Tree Object representing the contents of a users desktop as
368: * TreeNodes. Each node representing either a Channel or a Container.
369: *
370: * @return A Tree Object representing the Desktop content
371: */
372: public Tree getTree() {
373: log(Level.FINEST, "Get Tree Invoked");
374: if (cTree == null) {
375: cTree = createTree(getCurrentView());
376: }
377: return cTree;
378: }
379:
380: /**
381: * Receives the Tree object from JSF and sets it into the bean
382: *
383: * @param tree Tree Object reperenting the tree from the form submission
384: */
385: public void setTree(Tree tree) {
386: log(Level.FINEST, "Set Tree Invoked");
387: cTree = tree;
388: }
389:
390: /**
391: * Handles the event that occurs when the user changes the selected viewmenu
392: *
393: * @param event ActionEvent
394: */
395: public void viewChange(ActionEvent event) {
396: log(Level.FINEST, "Value of currentView : " + currentView);
397: // If the selected view is not Physical tree and it does not exist
398: // in the list of top level containers then most likely the currentView
399: // field is out of sync. Call initCurrentView to reset its value
400: if (!currentView.equals(TYPE_PHYSICAL_TREE)) {
401: if (!topNodes.contains(currentView)) {
402: initCurrentView();
403: log(Level.FINEST, "CurrentView value updated to :"
404: + currentView);
405: }
406: }
407: // Reset the tree content
408: cTree = createTree(getCurrentView());
409: }
410:
411: private Tree createTree(String type) {
412:
413: log(Level.FINEST, "Attempting to Create Tree of type: " + type);
414: log(Level.FINEST, "Fetching Data for DN: " + getCurrentDN());
415:
416: // Set the selected viewtype which is name of container into session
417: setSessionAttribute(ATTR_SELECTED_TREE_CONTAINER, currentView);
418:
419: // Get the selected node from the session attribute
420: selectedChannel = (String) getSessionAttribute(ATTR_SELECTED_TREE_CHANNEL);
421: // If its not available in the session then try to get it from the
422: // EditProperties bean
423: if (selectedChannel == null) {
424: FacesContext context = FacesContext.getCurrentInstance();
425: VariableResolver vr = context.getApplication()
426: .getVariableResolver();
427: Object obj = (Object) vr.resolveVariable(context,
428: "EditPropertiesBean");
429: if ((obj != null) && (obj instanceof EditPropertiesBean)) {
430: EditPropertiesBean epropsbean = (EditPropertiesBean) obj;
431: selectedChannel = epropsbean.getChannelName();
432: }
433: }
434:
435: // Initialize a new tree
436: Tree tree = new Tree();
437: tree.setClientSide(true);
438: tree.setExpanded(true);
439: tree.setText(getI18NString("label.content.unavailable"));
440: tree.setId(TREE_ID);
441: tree.setTransient(true);
442:
443: // Setting the params and signature
444: Object[] params;
445: String[] signature;
446:
447: try {
448:
449: String methodName = null;
450: if (type.equals(TYPE_PHYSICAL_TREE)) {
451: params = new Object[] { getCurrentDN() };
452: signature = new String[] { "java.lang.String" };
453: methodName = "getPhysicalHierarchy";
454: } else {
455: log(Level.FINEST, "Root Container: " + currentView);
456: params = new Object[] { getCurrentDN(), currentView };
457: signature = new String[] { "java.lang.String",
458: "java.lang.String" };
459: methodName = "getVisualHierarchy";
460: }
461:
462: // Get the Display Profile MBean Object Name
463: ObjectName objName = AdminClientUtil
464: .getDisplayProfileMBeanObjectName(
465: AdminClientUtil.DEFAULT_DOMAIN,
466: getPortalId());
467:
468: // reset the rootTreeNode to null
469: rootTreeNode = null;
470:
471: // Invoke the get method on the portal Desktop MBean
472: Object[] rootNode = (Object[]) getMBeanServerConnection()
473: .invoke(objName, methodName, params, signature);
474:
475: if (rootNode != null) {
476: // Populate the treeNodes with the data from the mbean
477: populateTree(null, rootNode);
478:
479: // Because of a limitation/bug in JSF the following is needed
480: List topLevelNodes = new ArrayList();
481: topLevelNodes.addAll(rootTreeNode.getChildren());
482: // if the treeNodes are directly added to tree there is data loss.
483:
484: tree.setText(rootTreeNode.getText());
485: tree.getChildren().addAll(topLevelNodes);
486: tree.getFacets().put(tree.IMAGE_FACET_KEY,
487: getNodeImage(TYPE_ROOT_CONTAINER_NODE));
488: Hyperlink tLink = getTreeNodeLink(rootTreeNode
489: .getText());
490: // Set the onClick method to clear the highlight of child nodes
491: // This is a hack to workaround LH tree issue
492: tLink
493: .setOnClick("clearAllHighlight('TreeViewer:cTree');");
494: // If the node name is _root (DP XML Tree) localize this string
495: // to DP_ROOT
496: if (tLink.getText().equals("_root")) {
497: tLink
498: .setText(getI18NString("edit.properties.dproot.label"));
499: }
500: tree.getFacets().put(tree.CONTENT_FACET_KEY, tLink);
501:
502: if (selectedNode != null) {
503: tree.selectTreeNode(selectedNode);
504: }
505:
506: } else {
507: // Log warning that the mbean method returned bad data
508: log(Level.WARNING, "MBean Returned a NULL");
509: }
510:
511: } catch (Exception e) {
512: log(Level.SEVERE,
513: "TreeViewerBean.createTree(): Error Fetching Data",
514: e);
515: }
516:
517: return tree;
518:
519: }
520:
521: /**
522: * Using recursion, prepares a tree structure of TreeNode objects from the
523: * data that is passed to it. It picksup the current node which is an Object
524: * Array. It prepares a TreeNode out of the data in the Object Array.
525: * The last element in the Object Array can be an ArrayList. Each element in
526: * this ArrayList represents a child to the current node.
527: *
528: * @param parent A TreeNode object representing the parent to current node
529: * @param currNode An Object Array. This method expects the Object array to
530: * have three elements.
531: * currNode[0] - A String representing the name of the current node
532: * currNode[1] - A String representing the type of the current node
533: * currNode[3] - An ArrayList representing the children of the current
534: * node.
535: */
536: private void populateTree(TreeNode parent, Object[] currNode) {
537:
538: TreeNode currentTreeNode = null;
539: if (currNode != null && currNode.length == 3) {
540: // Get the components of this node
541: String name = (String) currNode[0];
542: String type = (String) currNode[1];
543:
544: // Create and add TreeNode representing the current
545: // node to the parent of the current node.
546: currentTreeNode = createTreeNode(name, type);
547: log(Level.FINEST, "Created Node: "
548: + currentTreeNode.getText());
549:
550: // If the parent node does not have a parent its parent.
551: // We are trying to add this newly created tnode is the first object
552: // in the tree
553: if (parent == null) {
554: // So make the newly created tnode the rootTreeNode.
555: rootTreeNode = currentTreeNode;
556: } else {
557: // Else add the newly created tnode as a child of the parent
558: // TreeNode
559: log(Level.FINEST, "Adding: "
560: + currentTreeNode.getText() + " To Parent: "
561: + parent.getText());
562: parent.getChildren().add(currentTreeNode);
563: }
564:
565: // If there are child nodes under the current node process them
566: List children = (List) currNode[2];
567: if (children != null && !children.isEmpty()) {
568: Iterator itr = children.iterator();
569: while (itr.hasNext()) {
570: Object[] childData = (Object[]) itr.next();
571: populateTree(currentTreeNode, childData);
572: }
573: } else {
574: log(Level.FINEST, "No children for Current Node: "
575: + currentTreeNode.getText());
576: }
577: }
578: }
579:
580: /**
581: * Creates a TreeNode object that can be used to populate a tree
582: *
583: * @param name A String representing the Text of this TreeNode
584: * @param type A String value representing the type of this node
585: * @return TreeNode object
586: */
587: private TreeNode createTreeNode(String name, String type) {
588:
589: TreeNode tnode = new TreeNode();
590: // Suffix C_ to take care of id issues if channelname starts with number
591: tnode.setId("C_" + name.replace('/', '_'));
592: tnode.setText(name);
593: Map nodeFacets = tnode.getFacets();
594: nodeFacets.put(tnode.IMAGE_FACET_KEY, getNodeImage(type));
595: nodeFacets.put(tnode.CONTENT_FACET_KEY, getTreeNodeLink(name));
596:
597: // Expand the node if its a container node
598: if (Integer.parseInt(type) < 3) {
599: tnode.setExpanded(true);
600: }
601:
602: if (name.equalsIgnoreCase(selectedChannel)) {
603: selectedNode = tnode;
604: }
605:
606: return tnode;
607: }
608:
609: /**
610: * Used by the createTreeNode method to create an ImageComponent thats
611: * embedded into the TreeNode as a facet
612: *
613: * @param type A String representing the type of the Node.
614: * @return A new ImageComponent Object
615: */
616: private ImageComponent getNodeImage(String type) {
617:
618: String iconUrl = "";
619: String altText = "";
620: boolean isDesktopView = !currentView.equals(TYPE_PHYSICAL_TREE);
621:
622: if (type.equals(TYPE_ROOT_CONTAINER_NODE)) {
623: iconUrl = ROOT_CONTAINER_ICON;
624: altText = getI18NString("alt.root.container");
625: } else if (type.equals(TYPE_VISIBLE_CHANNEL_NODE)) {
626: iconUrl = VISIBLE_CHANNEL_ICON;
627: if (isDesktopView) {
628: altText = getI18NString("alt.visible.channel");
629: } else {
630: altText = getI18NString("alt.channel");
631: }
632: } else if (type.equals(TYPE_VISIBLE_PORTLET_CHANNEL_NODE)) {
633: iconUrl = VISIBLE_PORTLET_CHANNEL_ICON;
634: if (isDesktopView) {
635: altText = getI18NString("alt.visible.portlet.channel");
636: } else {
637: altText = getI18NString("alt.portlet.channel");
638: }
639: } else if (type
640: .equals(TYPE_VISIBLE_REMOTE_PORTLET_CHANNEL_NODE)) {
641: iconUrl = VISIBLE_REMOTE_PORTLET_CHANNEL_ICON;
642: if (isDesktopView) {
643: altText = getI18NString("alt.visible.remote.portlet.channel");
644: } else {
645: altText = getI18NString("alt.remote.portlet.channel");
646: }
647: } else if (type.equals(TYPE_VISIBLE_CONTAINER_NODE)) {
648: iconUrl = VISIBLE_CONTAINER_ICON;
649: if (isDesktopView) {
650: altText = getI18NString("alt.visible.container");
651: } else {
652: altText = getI18NString("alt.container");
653: }
654: } else if (type.equals(TYPE_INVISIBLE_CHANNEL_NODE)) {
655: iconUrl = INVISIBLE_CHANNEL_ICON;
656: altText = getI18NString("alt.invisible.channel");
657: } else if (type.equals(TYPE_INVISIBLE_PORTLET_CHANNEL_NODE)) {
658: iconUrl = INVISIBLE_PORTLET_CHANNEL_ICON;
659: altText = getI18NString("alt.invisible.portlet.channel");
660: } else if (type
661: .equals(TYPE_INVISIBLE_REMOTE_PORTLET_CHANNEL_NODE)) {
662: iconUrl = INVISIBLE_REMOTE_PORTLET_CHANNEL_ICON;
663: altText = getI18NString("alt.invisible.remote.portlet.channel");
664: } else if (type.equals(TYPE_INVISIBLE_CONTAINER_NODE)) {
665: iconUrl = INVISIBLE_CONTAINER_ICON;
666: altText = getI18NString("alt.invisible.container");
667: }
668:
669: ImageComponent img = new ImageComponent();
670: img.setId("Image");
671: img.setUrl(iconUrl);
672: img.setAlt(altText);
673: img.setToolTip(altText);
674: return img;
675: }
676:
677: /**
678: * Used by the createTreeNode method to create a link that is set into the
679: * TreeNode.
680: * @param name A String representing the name of the TreeNode
681: * @return A newly created Hyperlink object
682: */
683: private Hyperlink getTreeNodeLink(String name) {
684:
685: // Prepare the display name for the node
686: String displayName = name;
687: int idx = name.lastIndexOf("/");
688: if (idx > -1) {
689: displayName = name.substring(idx + 1);
690: }
691: String encodedName = null;
692: try {
693: encodedName = URLEncoder.encode(name, DEFAULT_CHARSET);
694: } catch (UnsupportedEncodingException uee) {
695: encodedName = name;
696: }
697: Hyperlink hl = new Hyperlink();
698: hl.setId("Link");
699: hl.setToolTip(name);
700: hl.setUrl("/faces/desktop/DesktopObjectManager.jsp?"
701: + ATTR_SELECTED_CHANNEL_NAME + "=" + encodedName + "&"
702: + ATTR_NESTED_PROPERTY_NAME + "=null");
703: hl.setTarget("dmgrdata");
704: hl.setText(displayName);
705:
706: /** Below logic is needed only if an action listener needs to be added
707: try {
708: Class actionListenerArgs[] = { ActionEvent.class };
709: FacesContext context = FacesContext.getCurrentInstance();
710: Application app = context.getApplication();
711: MethodBinding mb = app.createMethodBinding(
712: "#{TreeViewerBean.nodeClick}",
713: actionListenerArgs);
714: hl.setActionListener(mb);
715: } catch (Exception e) {
716:
717: }
718: **/
719:
720: return hl;
721: }
722:
723: /**
724: * Gets a localized string from the resoucebundle
725: * @param key A key string
726: * @return A localized String for the key
727: */
728: private String getI18NString(String key) {
729: return getLocalizedString("desktop", key);
730: }
731:
732: }
|