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