001 package org.apache.myfaces.tobago.taglib.component;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements. See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache License, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020 import org.apache.myfaces.tobago.apt.annotation.BodyContent;
021 import org.apache.myfaces.tobago.apt.annotation.Tag;
022 import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
023 import org.apache.myfaces.tobago.component.ComponentUtil;
024 import org.apache.myfaces.tobago.event.TabChangeListener;
025 import org.apache.myfaces.tobago.event.TabChangeSource;
026 import org.apache.myfaces.tobago.event.TabChangeListenerValueBindingDelegate;
027 import org.apache.myfaces.tobago.event.TabChangeEvent;
028
029 import org.apache.commons.logging.Log;
030 import org.apache.commons.logging.LogFactory;
031
032 import javax.faces.component.UIComponent;
033 import javax.faces.context.FacesContext;
034 import javax.faces.el.ValueBinding;
035 import javax.faces.el.MethodBinding;
036 import javax.faces.webapp.UIComponentTag;
037 import javax.faces.application.Application;
038 import javax.servlet.jsp.JspException;
039 import javax.servlet.jsp.tagext.TagSupport;
040
041 /**
042 * Register an TabChangedListener instance on the UIComponent
043 * associated with the closest parent UIComponent custom action.
044 */
045 @Tag(name = "tabChangeListener", bodyContent = BodyContent.EMPTY)
046 public class TabChangeListenerTag extends TagSupport {
047
048 private static final long serialVersionUID = -419199086962377873L;
049
050 private static final Class[] TAB_CHANGE_LISTENER_ARGS = new Class[] {TabChangeEvent.class};
051
052 private static final Log LOG = LogFactory.getLog(TabChangeListenerTag.class);
053
054 /**
055 * <p>The fully qualified class name of the {@link TabChangeListener}
056 * instance to be created.</p>
057 */
058 private String type;
059 private String binding;
060 private String listener;
061
062 /**
063 * Fully qualified Java class name of a TabChangeListener to be
064 * created and registered.
065 */
066 @TagAttribute(required = true)
067 public void setType(String type) {
068 this.type = type;
069 }
070
071 /**
072 * The value binding expression to a TabChangeListener.
073 */
074 @TagAttribute
075 public void setBinding(String binding) {
076 this.binding = binding;
077 }
078
079
080 /**
081 * A method binding expression to a processTabChange(TabChangeEvent tabChangeEvent) method.
082 */
083 @TagAttribute
084 public void setListener(String listener) {
085 this.listener = listener;
086 }
087
088 /**
089 * <p>Create a new instance of the specified {@link TabChangeListener}
090 * class, and register it with the {@link javax.faces.component.UIComponent} instance associated
091 * with our most immediately surrounding {@link javax.faces.webapp.UIComponentTag} instance, if
092 * the {@link javax.faces.component.UIComponent} instance was created by this execution of the
093 * containing JSP page.</p>
094 *
095 * @throws JspException if a JSP error occurs
096 */
097 public int doStartTag() throws JspException {
098
099 // Locate our parent UIComponentTag
100 UIComponentTag tag =
101 UIComponentTag.getParentUIComponentTag(pageContext);
102 if (tag == null) {
103 // TODO Message resource i18n
104 throw new JspException("Not nested in faces tag");
105 }
106
107 if (!tag.getCreated()) {
108 return (SKIP_BODY);
109 }
110
111 UIComponent component = tag.getComponentInstance();
112 if (component == null) {
113 // TODO Message resource i18n
114 throw new JspException("Component Instance is null");
115 }
116 if (!(component instanceof TabChangeSource)) {
117 // TODO Message resource i18n
118 throw new JspException("Component " + component.getClass().getName() + " is not instanceof TabChangeSource");
119 }
120 TabChangeSource changeSource = (TabChangeSource) component;
121
122 TabChangeListener handler = null;
123 ValueBinding valueBinding = null;
124 if (binding != null && UIComponentTag.isValueReference(binding)) {
125 valueBinding = ComponentUtil.createValueBinding(binding);
126 if (valueBinding != null) {
127 Object obj = valueBinding.getValue(FacesContext.getCurrentInstance());
128 if (obj != null && obj instanceof TabChangeListener) {
129 handler = (TabChangeListener) obj;
130 }
131 }
132 }
133
134 if (handler == null && type != null) {
135 handler = createTabChangeListener(type);
136 if (handler != null && valueBinding != null) {
137 valueBinding.setValue(FacesContext.getCurrentInstance(), handler);
138 }
139 }
140 if (handler != null) {
141 if (valueBinding != null) {
142 changeSource.addTabChangeListener(new TabChangeListenerValueBindingDelegate(type, valueBinding));
143 } else {
144 changeSource.addTabChangeListener(handler);
145 }
146 }
147
148 if (listener != null && UIComponentTag.isValueReference(listener)) {
149 Application application = FacesContext.getCurrentInstance().getApplication();
150 MethodBinding methodBinding = application.createMethodBinding(listener, TAB_CHANGE_LISTENER_ARGS);
151 changeSource.setTabChangeListener(methodBinding);
152 }
153 // TODO else LOG.warn?
154 return (SKIP_BODY);
155 }
156
157
158 /**
159 * <p>Release references to any acquired resources.
160 */
161 public void release() {
162 this.type = null;
163 this.binding = null;
164 }
165
166 /**
167 * <p>Create and return a new {@link TabChangeListener} to be registered
168 * on our surrounding {@link javax.faces.component.UIComponent}.</p>
169 *
170 * @throws javax.servlet.jsp.JspException if a new instance cannot be created
171 */
172 protected TabChangeListener createTabChangeListener(String className) throws JspException {
173 try {
174 Class clazz = getClass().getClassLoader().loadClass(className);
175 return ((TabChangeListener) clazz.newInstance());
176 } catch (Exception e) {
177 throw new JspException(e);
178 }
179 }
180 }