001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.tags.tree;
020:
021: import org.apache.beehive.netui.tags.AbstractSimpleTag;
022: import org.apache.beehive.netui.tags.html.IUrlParams;
023: import org.apache.beehive.netui.tags.internal.PageFlowTagUtils;
024: import org.apache.beehive.netui.util.Bundle;
025:
026: import javax.servlet.http.HttpServletRequest;
027: import javax.servlet.jsp.JspException;
028: import javax.servlet.jsp.PageContext;
029: import javax.servlet.jsp.tagext.JspTag;
030: import java.io.IOException;
031: import java.util.ArrayList;
032: import java.util.Iterator;
033:
034: /**
035: * Instantiates a TreeElement object that will get added to the parent tag (either a Tree or
036: * another TreeItem).
037: * @jsptagref.tagdescription Adds a tree node to the parent node
038: * (either a {@link Tree} or another <netui:treeItem>).
039: * @example In this first sample, a TreeItem contained by a parent TreeItem or Tree will
040: * display with
041: * the label of "Login" and, when clicked, will navigate to the Login pageflow.
042: * <pre> <netui:treeItem action="/netui/login/Login.jpf">Login</netui:treeItem></pre>
043: * <p>In this next sample, a TreeItem contained by a parent TreeItem or Tree will display with
044: * the label of "Human Resources" and icon "folder16.gif" and most likely will have
045: * child TreeItem tags because it does not have an action and starts expanded.</p>
046: * <pre> <netui:treeItem icon="folder16.gif" expanded="true">
047: * <netui:treeLabel>Human Resources</netui:treeLabel>
048: * ...
049: * </netui:treeItem></pre>
050: * @netui:tag name="treeItem" body-content="scriptless" description="Instantiates a TreeElement object that will get added to the parent tag (either a Tree or another TreeItem)."
051: * @see Tree
052: * @see org.apache.beehive.netui.tags.tree.TreeElement
053: */
054: public class TreeItem extends AbstractSimpleTag implements IUrlParams {
055: private String _action; // The action raised when the TreeItem is selected
056: private String _clientAction; // A client action that may run instead of the action.
057: private boolean _expanded; // boolean to indicate if the tree is expanded
058: private boolean _expandOnServer; // boolean to indicate if the tree should be expanded on the server
059: private boolean _disabled; // boolean to indicate if the tree should be expanded on the server
060: private String _href; // href link called when the TreeItem is selected
061: private String _scope; // the scope so that we support multiple page flows
062: private String _icon; // The icon representing the TreeItem
063: private TreeElement _treeElement; // pointer to the tree node
064: private String _target; // The target window for the selection event
065: private String _title; // The title (if there is one)
066: private String _tagId; // tag that should uniquely indentify a tree. Required for multiple tree using auto expand
067: private ArrayList _attributes; // array list of attributes
068: private InheritableState _state; // the state
069:
070: private boolean _child = false; // has a child set the content
071: private String _childLabel; // value set by a TreeLabel
072: private String _childContent; // value set by a TreeItemContent tag
073:
074: /**
075: * Return the name of the Tag.
076: */
077: public String getTagName() {
078: return "TreeItem";
079: }
080:
081: //*********************************** TAG PROPERTIES ***************************************************************
082:
083: /**
084: * Set the TreeItem's action.
085: * @param action the action.
086: * @jsptagref.attributedescription The action to invoke when this tree node is clicked.
087: * @jsptagref.databindable true
088: * @jsptagref.attributesyntaxvalue <i>string_or_expression</i>
089: * @netui:attribute required="false" rtexprvalue="true"
090: * description="Set the TreeItem's action."
091: */
092: public void setAction(String action) throws JspException {
093: _action = setRequiredValueAttribute(action, "action");
094: }
095:
096: /**
097: * Sets an action to run on the client when the tree is selected.
098: * @param action the client action.
099: * @jsptagref.attributedescription Sets an action to run on the client when the tree node is selected.
100: * @jsptagref.databindable true
101: * @jsptagref.attributesyntaxvalue <i>string_or_expression</i>
102: * @netui:attribute required="false" rtexprvalue="true"
103: * description="Sets an action to run on the client when the tree is selected."
104: */
105: public void setClientAction(String action) throws JspException {
106: _clientAction = setRequiredValueAttribute(action,
107: "clientAction");
108: }
109:
110: /**
111: * Set the ID of the tag.
112: * @param tagId the tagId.
113: * @jsptagref.attributedescription Sets of the id attribute of the tree node
114: * @jsptagref.databindable true
115: * @jsptagref.attributesyntaxvalue <i>string_or_expression</i>
116: * @netui:attribute required="false" rtexprvalue="true"
117: * description="Set the ID of the tag."
118: */
119: public void setTagId(String tagId) throws JspException {
120: _tagId = setRequiredValueAttribute(tagId, "tagId");
121: }
122:
123: /**
124: * Sets the TreeItem expansion state.
125: * @param expanded the expanded state.
126: * @jsptagref.attributedescription Sets the expanded/collapsed state of the tree node.
127: * @jsptagref.databindable true
128: * @jsptagref.attributesyntaxvalue <i>boolean_or_booleanExpression</i>
129: * @netui:attribute required="false" rtexprvalue="true"
130: * description="Sets the TreeItem expansion state."
131: */
132: public void setExpanded(boolean expanded) {
133: _expanded = expanded;
134: }
135:
136: /**
137: * Disables the TreeItem.
138: * @param disabled the enabled/disabled state.
139: * @jsptagref.attributedescription Boolean. Determines if the tree node is enabled or disabled.
140: * @jsptagref.databindable true
141: * @jsptagref.attributesyntaxvalue <i>boolean_or_booleanExpression</i>
142: * @netui:attribute required="false" rtexprvalue="true"
143: * description="Sets the TreeItem expansion state."
144: */
145: public void setDisabled(boolean disabled) {
146: _disabled = disabled;
147: }
148:
149: /**
150: * Set the value of the expandOnServer attribute. If the attribute is <code>true</code>
151: * and <code>runAtClient</code> is also true, then an expansion on this node will cause that
152: * to happen on the server. When runAtClient is false, all expansions will happen on the server.
153: * @jsptagref.attributedescription If this attribute is <code>true</code>
154: * and <code>runAtClient</code> is also true, then an expansion on this node will cause that
155: * to happen on the server. When runAtClient is false, all expansions will happen on the server.
156: * @jsptagref.databindable true
157: * @jsptagref.attributesyntaxvalue <i>boolean_or_booleanExpression</i>
158: * @param expandOnServer boolean value indicating if the node should be expanded on the server.
159: * @netui:attribute required="false" rtexprvalue="true"
160: * description="If running on the client, cause the node to be expanded and contracted on the server."
161: */
162: public void setExpandOnServer(boolean expandOnServer) {
163: _expandOnServer = expandOnServer;
164: }
165:
166: /**
167: * Sets the TreeItem's href.
168: * @param href the href
169: * @jsptagref.attributedescription The href attribute of the node's link.
170: * @jsptagref.databindable true
171: * @jsptagref.attributesyntaxvalue <i>string_or_expression</i>
172: * @netui:attribute required="false" rtexprvalue="true"
173: * description="sets the TreeItem's href."
174: */
175: public void setHref(String href) throws JspException {
176: _href = setRequiredValueAttribute(href, "href");
177: }
178:
179: /**
180: * Sets the TreeItems title.
181: * @param title
182: * @jsptagref.attributedescription The node's title
183: * @jsptagref.databindable true
184: * @jsptagref.attributesyntaxvalue <i>string_or_expression</i>
185: * @netui:attribute required="false" rtexprvalue="true"
186: * description="Sets the TreeItems title."
187: */
188: public void setTitle(String title) {
189: _title = setNonEmptyValueAttribute(title);
190: }
191:
192: /**
193: * Set the target scope for this tree node's URI. Any page flow that handles the URI will be made active within the
194: * given scope. Scopes allow multiple page flows to be active within the same user session; page flows in different
195: * scopes do not in general interact with each other. This attribute is commonly used in conjunction with the
196: * <code>target</code> attribute ({@link #setTarget}) to invoke a new page flow in a separate window.
197: * @param scope a String that identifies the scope in which the target page flow will be made active.
198: * @jsptagref.attributedescription Set the target scope for this tree node's URI.
199: * Any page flow that handles the URI will be made active within the given scope.
200: * Scopes allow multiple page flows to be active within the same user session; page flows
201: * in different scopes do not in general interact with each other. This attribute is
202: * commonly used in conjunction with the <code>target</code> attribute
203: * to invoke a new page flow in a separate window.
204: * @jsptagref.databindable true
205: * @jsptagref.attributesyntaxvalue <i>string_or_expression</i>
206: * @netui:attribute required="false" rtexprvalue="true"
207: * description="Set the target scope for this tree node's URI."
208: */
209: public void setScope(String scope) {
210: _scope = setNonEmptyValueAttribute(scope);
211: }
212:
213: /**
214: * Sets the TreeItem icon URI.
215: * @param icon the icon URI
216: * @jsptagref.attributedescription The icon URI.
217: * @jsptagref.databindable true
218: * @jsptagref.attributesyntaxvalue <i>string_or_expression</i>
219: * @netui:attribute required="false" rtexprvalue="true"
220: * description="Sets the icon representing this tree item."
221: */
222: public void setIcon(String icon) {
223: _icon = setNonEmptyValueAttribute(icon);
224: }
225:
226: //********************************** METHODS CALLED BY CHILD TAGS TO SET STATE **********************************
227:
228: /**
229: * This method is called by children tags of the TreeItem. If there is a <code>TreeLabel</code>
230: * it will set the text of the label. A child <code>TreeLabel</code> will override the <code>label</code>
231: * attribute.
232: * @param label The text of the Label to be displayed for this TreeItem.
233: */
234: public void setItemLabel(String label) {
235: _child = true;
236: _childLabel = label;
237: }
238:
239: /**
240: * @param content
241: */
242: public void setItemContent(String content) {
243: _child = true;
244: _childContent = content;
245: }
246:
247: /**
248: * This method is called by the children tags of the TreeItem. If there is a <code>TreeHtmlAttribute</code>
249: * it will set the attribute name and value.
250: * @param attr
251: */
252: public void setItemAttribute(TreeHtmlAttributeInfo attr) {
253: _child = true;
254: if (_attributes == null)
255: _attributes = new ArrayList();
256: _attributes.add(attr);
257: }
258:
259: public void setItemInheritableState(InheritableState state) {
260: _child = true;
261: _state = state;
262: }
263:
264: public void setAddedChild() {
265: _child = true;
266: }
267:
268: /**
269: * @return TreeElement
270: */
271: public TreeElement getNode() {
272: return _treeElement;
273: }
274:
275: /**
276: * Sets the window target.
277: * @param target the window target.
278: * @jsptagref.attributedescription Sets the window target of the node's link.
279: * @jsptagref.databindable true
280: * @jsptagref.attributesyntaxvalue <i>string_or_expression</i>
281: * @netui:attribute required="false" rtexprvalue="true"
282: * description="Sets the window target."
283: */
284: public void setTarget(String target) {
285: _target = target;
286: }
287:
288: public void addParameter(String name, Object value, String facet)
289: throws JspException {
290: _treeElement.addParameter(name, value, facet);
291: }
292:
293: //************************************* TAG METHODS ****************************************************************
294:
295: /**
296: * Instantiate a new TreeElement.
297: * @throws JspException if a JSP exception has occurred
298: */
299: public void doTag() throws JspException, IOException {
300: // It is only legal to set either an action or an href, this will verify we have exactly one.
301: // report an error when there is more than one specified.
302: int have = 0;
303: if (_href != null)
304: have++;
305: if (_action != null)
306: have++;
307: if (have > 1) {
308: String s = Bundle.getString("Tags_Node_InvalidNode",
309: new Object[] { "href, action" });
310: registerTagError(s, null);
311: }
312:
313: // If we have specified an action, then we need to verify that the action is a valid action
314: PageContext pageContext = getPageContext();
315: if (_action != null) {
316: HttpServletRequest request = (HttpServletRequest) pageContext
317: .getRequest();
318: boolean isAction = PageFlowTagUtils.isAction(request,
319: _action);
320: if (!isAction) {
321: registerTagError(Bundle.getString("Tags_BadAction",
322: _action), null);
323: }
324: }
325:
326: // create the tree node
327: JspTag parentTag = getParent();
328: if (parentTag instanceof Tree) {
329: _treeElement = new TreeRootElement();
330: } else {
331: _treeElement = new TreeElement();
332: }
333:
334: // the the values
335: _treeElement.setIcon(_icon);
336: _treeElement.setClientAction(_clientAction);
337: _treeElement.setScope(_scope);
338: _treeElement.setTitle(_title);
339: _treeElement.setTagId(_tagId);
340: _treeElement.setExpandOnServer(_expandOnServer);
341: _treeElement.setExpanded(_expanded);
342: _treeElement.setDisabled(_disabled);
343: _treeElement.setTarget(_target);
344: _treeElement.setHref(_href);
345: _treeElement.setAction(_action);
346:
347: boolean inlineError = false;
348: if (hasErrors()) {
349: String s = getInlineError();
350: if (s == null)
351: s = Bundle.getString("Tags_TreeItemErrorNoInline");
352: else
353: inlineError = true;
354: _treeElement.setContent(s);
355: }
356:
357: // insert the node into the parent node or into the tree itself.
358: if (parentTag instanceof Tree) {
359: Tree parentTree = (Tree) parentTag;
360: if (parentTree.getRootNode() != null) {
361: String s = Bundle
362: .getString("Tags_TreeMultipleRootNodes");
363: parentTree.registerTagError(s, null);
364: //reportErrors();
365: return;
366: }
367: parentTree.setRootNode(_treeElement);
368: } else if (parentTag instanceof TreeItem) {
369: TreeItem parentNode = (TreeItem) parentTag;
370: parentNode.getNode().addChild(_treeElement);
371: parentNode.setAddedChild();
372: } else {
373: // The parent is neither a Tree or a TreeItem so we must report an error
374: String s = Bundle.getString("Tags_InvalidNodeParent");
375: registerTagError(s, null);
376: reportErrors();
377: return;
378: }
379:
380: String content = getBufferBody(true);
381: if (!_child) {
382: if (content != null)
383: _childLabel = content;
384: }
385:
386: // if there was a childLabel set then we need to update the label value for the tag.
387: if (_childLabel != null) {
388: _treeElement.setLabel(_childLabel);
389: }
390:
391: if (hasErrors()) {
392: if (!inlineError)
393: reportErrors();
394: return;
395: }
396:
397: // if there was content defined for the node then we will set it on the node...
398: if (_childContent != null) {
399: _treeElement.setContent(_childContent);
400: }
401:
402: // if there was inherited state set it now...
403: if (_state != null) {
404: _treeElement.setInheritableState(_state);
405: }
406:
407: // if there is attribute then we should insert that into the TreeElement
408: if (_attributes != null && _attributes.size() > 0) {
409: Iterator it = _attributes.iterator();
410: while (it.hasNext()) {
411: TreeHtmlAttributeInfo jsi = (TreeHtmlAttributeInfo) it
412: .next();
413: _treeElement.addAttribute(jsi);
414: }
415: }
416: }
417: }
|