1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.internal.component;
21
22 import org.apache.myfaces.tobago.component.Attributes;
23 import org.apache.myfaces.tobago.event.TabChangeEvent;
24 import org.apache.myfaces.tobago.event.TabChangeListener;
25 import org.apache.myfaces.tobago.event.TabChangeSource;
26 import org.apache.myfaces.tobago.event.TobagoActionSource;
27 import org.apache.myfaces.tobago.model.SwitchType;
28 import org.apache.myfaces.tobago.util.FacesELUtils;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import javax.el.MethodExpression;
33 import javax.el.ValueExpression;
34 import javax.faces.component.UIComponent;
35 import javax.faces.component.behavior.ClientBehaviorHolder;
36 import javax.faces.context.FacesContext;
37 import javax.faces.event.AbortProcessingException;
38 import javax.faces.event.ActionListener;
39 import javax.faces.event.FacesEvent;
40 import javax.faces.event.PhaseId;
41 import java.io.IOException;
42 import java.lang.invoke.MethodHandles;
43 import java.util.ArrayList;
44 import java.util.List;
45
46
47
48
49 public abstract class AbstractUITabGroup extends AbstractUIPanelBase
50 implements TabChangeSource, TobagoActionSource, ClientBehaviorHolder {
51
52 private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
53
54 @Override
55 public void encodeChildren(final FacesContext facesContext) throws IOException {
56 }
57
58 @Override
59 public void encodeEnd(final FacesContext facesContext) throws IOException {
60 super.encodeEnd(facesContext);
61 setRenderedIndex(getSelectedIndex());
62 }
63
64
65 @Override
66 public boolean getRendersChildren() {
67 return true;
68 }
69
70 @Override
71 public void queueEvent(final FacesEvent event) {
72 if (this == event.getSource()) {
73 if (isImmediate() || getSwitchType() == SwitchType.client) {
74
75 event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
76 } else {
77 event.setPhaseId(PhaseId.INVOKE_APPLICATION);
78 }
79 }
80 super.queueEvent(event);
81 }
82
83 public AbstractUITab[] getTabs() {
84 final List<AbstractUITab> tabs = new ArrayList<>();
85 for (final UIComponent kid : getChildren()) {
86 if (kid instanceof AbstractUITab) {
87
88 tabs.add((AbstractUITab) kid);
89
90 } else {
91 LOG.error("Invalid component in UITabGroup: " + kid);
92 }
93 }
94 return tabs.toArray(new AbstractUITab[0]);
95 }
96
97 public AbstractUITab getActiveTab() {
98 return getTab(getSelectedIndex());
99 }
100
101
102 @Override
103 public void processDecodes(final FacesContext context) {
104 if (!(getSwitchType() == SwitchType.client)) {
105
106 if (context == null) {
107 throw new NullPointerException("context");
108 }
109 if (!isRendered()) {
110 return;
111 }
112 int index = 0;
113 for (final UIComponent child : getChildren()) {
114 if (child instanceof AbstractUITab) {
115 final AbstractUITab tab = (AbstractUITab) child;
116 if (tab.isRendered()) {
117 if (getRenderedIndex() == index) {
118 tab.processDecodes(context);
119 }
120 }
121 index++;
122 }
123 }
124
125
126 for (final UIComponent facet : getFacets().values()) {
127 facet.processDecodes(context);
128 }
129 try {
130 decode(context);
131 } catch (final RuntimeException e) {
132 context.renderResponse();
133 throw e;
134 }
135 } else {
136 super.processDecodes(context);
137 }
138 }
139
140 @Override
141 public void processValidators(final FacesContext context) {
142 if (!(getSwitchType() == SwitchType.client)) {
143 if (!isRendered()) {
144 return;
145 }
146 final AbstractUITab renderedTab = getTab(getRenderedIndex());
147 if (renderedTab != null) {
148 renderedTab.processValidators(context);
149 }
150 for (final UIComponent facet : getFacets().values()) {
151 facet.processValidators(context);
152 }
153 } else {
154 super.processValidators(context);
155 }
156 }
157
158 @Override
159 public void processUpdates(final FacesContext context) {
160 if (!(getSwitchType() == SwitchType.client)) {
161 if (!isRendered()) {
162 return;
163 }
164 final AbstractUITab renderedTab = getTab(getRenderedIndex());
165 if (renderedTab != null) {
166 renderedTab.processUpdates(context);
167 }
168 for (final UIComponent facet : getFacets().values()) {
169 facet.processUpdates(context);
170 }
171
172 } else {
173 super.processUpdates(context);
174 }
175 }
176
177 @Override
178 public void broadcast(final FacesEvent facesEvent) throws AbortProcessingException {
179 super.broadcast(facesEvent);
180 if (facesEvent instanceof TabChangeEvent && facesEvent.getComponent() == this) {
181 final TabChangeEvent event = (TabChangeEvent) facesEvent;
182
183 final MethodExpression methodExpression = getTabChangeListenerExpression();
184 if (methodExpression != null) {
185 FacesELUtils.invokeMethodExpression(FacesContext.getCurrentInstance(), methodExpression, facesEvent);
186 }
187
188
189
190
191
192
193
194
195 if (!(getSwitchType() == SwitchType.client)) {
196 final ActionListener defaultActionListener = getFacesContext().getApplication().getActionListener();
197 if (defaultActionListener != null) {
198 defaultActionListener.processAction(event);
199 }
200 }
201 final Integer index = event.getNewTabIndex();
202 final ValueExpression expression = getValueExpression(Attributes.selectedIndex.getName());
203 if (expression != null) {
204 expression.setValue(getFacesContext().getELContext(), index);
205 } else {
206 setSelectedIndex(index);
207 }
208 }
209 }
210
211 @Override
212 public void addTabChangeListener(final TabChangeListener listener) {
213 if (LOG.isWarnEnabled() && getSwitchType() == SwitchType.client) {
214 LOG.warn("Adding TabChangeListener to client side TabGroup!");
215 }
216 addFacesListener(listener);
217 }
218
219 @Override
220 public void removeTabChangeListener(final TabChangeListener listener) {
221 removeFacesListener(listener);
222 }
223
224 @Override
225 public TabChangeListener[] getTabChangeListeners() {
226 return (TabChangeListener[]) getFacesListeners(TabChangeListener.class);
227 }
228
229 public abstract Integer getRenderedIndex();
230
231 public abstract void setRenderedIndex(Integer index);
232
233 public abstract boolean isShowNavigationBar();
234
235 public abstract Integer getSelectedIndex();
236
237 public abstract void setSelectedIndex(Integer index);
238
239 public abstract SwitchType getSwitchType();
240
241 private AbstractUITab getTab(final int index) {
242 int i = 0;
243 for (final UIComponent component : getChildren()) {
244 if (component instanceof AbstractUITab) {
245 if (i == index) {
246 return (AbstractUITab) component;
247 }
248 i++;
249 } else {
250 LOG.error("Invalid component in UITabGroup: " + component);
251 }
252 }
253 LOG.error("Found no component with index: " + index + " childCount: " + getChildCount());
254 return null;
255 }
256
257
258
259
260 @Override
261 public void addActionListener(final ActionListener listener) {
262 addFacesListener(listener);
263 }
264
265
266
267
268 @Override
269 public ActionListener[] getActionListeners() {
270 return (ActionListener[]) getFacesListeners(ActionListener.class);
271 }
272
273
274
275
276 @Override
277 public void removeActionListener(final ActionListener listener) {
278 removeFacesListener(listener);
279 }
280 }