View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.custom.aliasbean;
20  
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  import java.io.IOException;
27  
28  import javax.faces.component.UIComponent;
29  import javax.faces.component.UIComponentBase;
30  import javax.faces.context.FacesContext;
31  import javax.faces.event.AbortProcessingException;
32  import javax.faces.event.FacesEvent;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.apache.myfaces.shared_tomahawk.util.RestoreStateUtils;
37  import org.apache.myfaces.shared_tomahawk.component.BindingAware;
38  
39  /**
40   * Holds several aliases that are configured by aliasBean tags.
41   * <p>
42   * The aliasBean tag must enclose all the components that are within the scope
43   * of the alias. When multiple aliasas are defined, this makes the page structure
44   * very clumsy; for example defining 5 aliases means the content must be nested
45   * 5 indentation levels deep. This tag instead allows the content block to be
46   * wrapped in just one AliasBeansScope tag, and then have AliasBean tags with
47   * empty bodies added as direct children of this component. The scope of the AliasBean
48   * tag still starts when the tag begins, but instead of ending when the tag ends
49   * the scope of the nested AliasBean tags extends to the end of this component.
50   * </p>
51   * 
52   * @JSFComponent
53   *   name = "t:aliasBeansScope"
54   *   tagClass = "org.apache.myfaces.custom.aliasbean.AliasBeansScopeTag"
55   *   tagHandler = "org.apache.myfaces.custom.aliasbean.AliasBeansScopeTagHandler"
56   *   
57   * @JSFJspProperty 
58   *   name = "rendered"
59   *   returnType = "boolean" 
60   *   tagExcluded = "true"
61   *   
62   * @JSFJspProperty
63   *   name = "binding"
64   *   returnType = "java.lang.String"
65   *   tagExcluded = "true"
66   *   
67   * @author Sylvain Vieujot (latest modification by $Author: lu4242 $)
68   * @version $Revision: 672986 $ $Date: 2008-06-30 23:13:55 -0500 (Mon, 30 Jun 2008) $
69   */
70  public class AliasBeansScope extends UIComponentBase implements BindingAware
71  {
72      static final Log log = LogFactory.getLog(AliasBeansScope.class);
73  
74      public static final String COMPONENT_TYPE = "org.apache.myfaces.AliasBeansScope";
75      public static final String COMPONENT_FAMILY = "javax.faces.Data";
76  
77      private ArrayList _aliases = new ArrayList();
78      transient FacesContext _context = null;
79  
80      void addAlias(Alias alias)
81      {
82          _aliases.add(alias);
83      }
84  
85      public String getFamily()
86      {
87          return COMPONENT_FAMILY;
88      }
89  
90      public String getRendererType() {
91        return null;
92      }
93  
94    public Object saveState(FacesContext context)
95      {
96          log.debug("saveState");
97          _context = context;
98  
99          return super.saveState(context);
100     }
101 
102     public void restoreState(FacesContext context, Object state)
103     {
104         log.debug("restoreState");
105         _context = context;
106 
107         super.restoreState(context, state);
108     }
109 
110     public Object processSaveState(FacesContext context)
111     {
112         if (context == null)
113             throw new NullPointerException("context");
114         if (isTransient())
115             return null;
116 
117         makeAliases(context);
118 
119         Map facetMap = null;
120         for (Iterator it = getFacets().entrySet().iterator(); it.hasNext();)
121         {
122             Map.Entry entry = (Map.Entry) it.next();
123             if (facetMap == null)
124                 facetMap = new HashMap();
125             UIComponent component = (UIComponent) entry.getValue();
126             if (!component.isTransient())
127             {
128                 facetMap.put(entry.getKey(), component.processSaveState(context));
129             }
130         }
131 
132         List childrenList = null;
133         if (getChildCount() > 0)
134         {
135             for (Iterator it = getChildren().iterator(); it.hasNext();)
136             {
137                 UIComponent child = (UIComponent) it.next();
138                 if (!child.isTransient())
139                 {
140                     if (childrenList == null)
141                         childrenList = new ArrayList(getChildCount());
142                     childrenList.add(child.processSaveState(context));
143                 }
144             }
145         }
146 
147         removeAliases(context);
148 
149         return new Object[]{saveState(context), facetMap, childrenList};
150     }
151 
152     public void processRestoreState(FacesContext context, Object state)
153     {
154         if (context == null)
155             throw new NullPointerException("context");
156         Object myState = ((Object[]) state)[0];
157 
158         restoreState(context, myState);
159 
160         makeAliases(context);
161 
162         Map facetMap = (Map) ((Object[]) state)[1];
163 
164         for (Iterator it = getFacets().entrySet().iterator(); it.hasNext();)
165         {
166             Map.Entry entry = (Map.Entry) it.next();
167             Object facetState = facetMap.get(entry.getKey());
168             if (facetState != null)
169             {
170                 ((UIComponent) entry.getValue()).processRestoreState(context, facetState);
171             }
172             else
173             {
174                 context.getExternalContext().log("No state found to restore facet " + entry.getKey());
175             }
176         }
177 
178         List childrenList = (List) ((Object[]) state)[2];
179         if (getChildCount() > 0)
180         {
181             int idx = 0;
182             for (Iterator it = getChildren().iterator(); it.hasNext();)
183             {
184                 UIComponent child = (UIComponent) it.next();
185                 Object childState = childrenList.get(idx++);
186                 if (childState != null)
187                 {
188                     child.processRestoreState(context, childState);
189                 }
190                 else
191                 {
192                     context.getExternalContext().log("No state found to restore child of component " + getId());
193                 }
194             }
195         }
196 
197         removeAliases(context);
198     }
199 
200     public void processValidators(FacesContext context)
201     {
202         log.debug("processValidators");
203         makeAliases(context);
204         super.processValidators(context);
205         removeAliases(context);
206     }
207 
208     public void processDecodes(FacesContext context)
209     {
210         log.debug("processDecodes");
211         makeAliases(context);
212         super.processDecodes(context);
213         removeAliases(context);
214     }
215 
216     public void processUpdates(FacesContext context)
217     {
218         log.debug("processUpdates");
219         makeAliases(context);
220         super.processUpdates(context);
221         removeAliases(context);
222     }
223 
224     public void encodeBegin(FacesContext context) throws IOException
225     {
226         log.debug("encodeBegin");
227         makeAliases(context);
228     }
229 
230     public void encodeEnd(FacesContext context)
231     {
232         log.debug("encodeEnd");
233         removeAliases(context);
234     }
235 
236     public void queueEvent(FacesEvent event)
237     {
238         super.queueEvent(new FacesEventWrapper(event, this));
239     }
240 
241     public void broadcast(FacesEvent event) throws AbortProcessingException
242     {
243         makeAliases();
244 
245         if (event instanceof FacesEventWrapper)
246         {
247             FacesEvent originalEvent = ((FacesEventWrapper) event).getWrappedFacesEvent();
248             originalEvent.getComponent().broadcast(originalEvent);
249         }
250         else
251         {
252             super.broadcast(event);
253         }
254 
255         removeAliases();
256     }
257 
258     void makeAliases(FacesContext context)
259     {
260         _context = context;
261         makeAliases();
262     }
263 
264     private void makeAliases()
265     {
266         for (Iterator i = _aliases.iterator(); i.hasNext();)
267             ((Alias) i.next()).make(_context);
268     }
269 
270     void removeAliases(FacesContext context)
271     {
272         _context = context;
273         removeAliases();
274     }
275 
276     private void removeAliases()
277     {
278         for (Iterator i = _aliases.iterator(); i.hasNext();)
279             ((Alias) i.next()).remove(_context);
280     }
281 
282     public void handleBindings()
283     {
284         makeAliases(getFacesContext());
285 
286         RestoreStateUtils.recursivelyHandleComponentReferencesAndSetValid(getFacesContext(), this, true);
287 
288         removeAliases(getFacesContext());
289     }
290 }