001: /*
002: * Copyright 2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package javax.faces.webapp;
017:
018: import javax.faces.application.Application;
019: import javax.faces.component.UIComponent;
020: import javax.faces.context.FacesContext;
021: import javax.faces.el.ValueBinding;
022: import javax.servlet.jsp.JspException;
023: import javax.servlet.jsp.PageContext;
024:
025: /**
026: * Base class for all JSP tags that represent a JSF UIComponent.
027: * <p>
028: * <i>Disclaimer</i>: The official definition for the behaviour of
029: * this class is the JSF specification but for legal reasons the
030: * specification cannot be replicated here. Any javadoc present on this
031: * class therefore describes the current implementation rather than the
032: * officially required behaviour, though it is believed that this class
033: * does comply with the specification.
034: *
035: * see Javadoc of <a href="http://java.sun.com/j2ee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a> for more.
036: *
037: * @author Manfred Geiler (latest modification by $Author: dennisbyrne $)
038: * @author Bruno Aranda
039: * @version $Revision: 519714 $ $Date: 2007-03-18 23:30:08 +0100 (So, 18 Mrz 2007) $
040: *
041: * @deprecated replaced by {@link UIComponentELTag}
042: */
043: public abstract class UIComponentTag extends UIComponentClassicTagBase {
044:
045: //tag attributes
046: private String _binding = null;
047: private String _rendered = null;
048:
049: private Boolean _suppressed = null;
050:
051: public UIComponentTag() {
052:
053: }
054:
055: public void release() {
056: super .release();
057:
058: _binding = null;
059: _rendered = null;
060: }
061:
062: /** Setter for common JSF xml attribute "binding". */
063: public void setBinding(String binding) throws JspException {
064: if (!isValueReference(binding)) {
065: throw new IllegalArgumentException("not a valid binding: "
066: + binding);
067: }
068: _binding = binding;
069: }
070:
071: /** Setter for common JSF xml attribute "rendered". */
072: public void setRendered(String rendered) {
073: _rendered = rendered;
074: }
075:
076: /**
077: * Return the nearest JSF tag that encloses this tag.
078: * @deprecated
079: */
080: public static UIComponentTag getParentUIComponentTag(
081: PageContext pageContext) {
082: UIComponentClassicTagBase parentTag = getParentUIComponentClassicTagBase(pageContext);
083:
084: return parentTag instanceof UIComponentTag ? (UIComponentTag) parentTag
085: : new UIComponentTagWrapper(parentTag);
086:
087: }
088:
089: /**
090: * Return true if the specified string contains an EL expression.
091: * <p>
092: * UIComponent properties are often required to be value-binding
093: * expressions; this method allows code to check whether that is
094: * the case or not.
095: */
096: public static boolean isValueReference(String value) {
097: if (value == null)
098: throw new NullPointerException("value");
099:
100: int start = value.indexOf("#{");
101: if (start < 0)
102: return false;
103:
104: int end = value.lastIndexOf('}');
105: return (end >= 0 && start < end);
106: }
107:
108: /**
109: * Create a UIComponent. Abstract method getComponentType is invoked to
110: * determine the actual type name for the component to be created.
111: *
112: * If this tag has a "binding" attribute, then that is immediately
113: * evaluated to store the created component in the specified property.
114: */
115: protected UIComponent createComponent(FacesContext context,
116: String id) {
117: String componentType = getComponentType();
118: if (componentType == null) {
119: throw new NullPointerException("componentType");
120: }
121:
122: if (_binding != null) {
123: Application application = context.getApplication();
124: ValueBinding componentBinding = application
125: .createValueBinding(_binding);
126: UIComponent component = application.createComponent(
127: componentBinding, context, componentType);
128: component.setId(id);
129: component.setValueBinding("binding", componentBinding);
130:
131: return component;
132: }
133:
134: UIComponent component = context.getApplication()
135: .createComponent(componentType);
136: component.setId(id);
137:
138: return component;
139:
140: }
141:
142: private boolean isFacet() {
143: return getParent() != null && getParent() instanceof FacetTag;
144: }
145:
146: /**
147: * Determine whether this component renders itself. A component
148: * is "suppressed" when it is either not rendered, or when it is
149: * rendered by its parent component at a time of the parent's choosing.
150: */
151: protected boolean isSuppressed() {
152: if (_suppressed == null) {
153: // we haven't called this method before, so determine the suppressed
154: // value and cache it for later calls to this method.
155:
156: if (isFacet()) {
157: // facets are always rendered by their parents --> suppressed
158: _suppressed = Boolean.TRUE;
159: return true;
160: }
161:
162: UIComponent component = getComponentInstance();
163:
164: // Does any parent render its children?
165: // (We must determine this first, before calling any isRendered method
166: // because rendered properties might reference a data var of a nesting UIData,
167: // which is not set at this time, and would cause a VariableResolver error!)
168: UIComponent parent = component.getParent();
169: while (parent != null) {
170: if (parent.getRendersChildren()) {
171: //Yes, parent found, that renders children --> suppressed
172: _suppressed = Boolean.TRUE;
173: return true;
174: }
175: parent = parent.getParent();
176: }
177:
178: // does component or any parent has a false rendered attribute?
179: while (component != null) {
180: if (!component.isRendered()) {
181: //Yes, component or any parent must not be rendered --> suppressed
182: _suppressed = Boolean.TRUE;
183: return true;
184: }
185: component = component.getParent();
186: }
187:
188: // else --> not suppressed
189: _suppressed = Boolean.FALSE;
190: }
191: return _suppressed.booleanValue();
192: }
193:
194: protected void setProperties(UIComponent component) {
195: if (getRendererType() != null) {
196: getComponentInstance().setRendererType(getRendererType());
197: }
198:
199: if (_rendered != null) {
200: if (isValueReference(_rendered)) {
201: ValueBinding vb = getFacesContext().getApplication()
202: .createValueBinding(_rendered);
203: component.setValueBinding("rendered", vb);
204: } else {
205: boolean b = Boolean.valueOf(_rendered).booleanValue();
206: component.setRendered(b);
207: }
208: }
209: }
210:
211: /**
212: * Class used to create an UIComponentTag from a UIComponentClassicTagBase
213: */
214: private static class UIComponentTagWrapper extends UIComponentTag {
215: public UIComponentTagWrapper(
216: UIComponentClassicTagBase classicTag) {
217: setId(classicTag.getId());
218: setJspId(classicTag.getJspId());
219: setParent(classicTag.getParent());
220: }
221:
222: public String getComponentType() {
223: return null;
224: }
225:
226: public String getRendererType() {
227: return null;
228: }
229:
230: protected UIComponent createComponent(FacesContext context,
231: String newId) {
232: return null;
233: }
234:
235: }
236:
237: @Override
238: protected boolean hasBinding() {
239: return _binding != null;
240: }
241:
242: }
|